Używam tej async.eachLimit
funkcji do kontrolowania maksymalnej liczby operacji na raz.
const { eachLimit } = require("async");
function myFunction() {
return new Promise(async (resolve, reject) => {
eachLimit((await getAsyncArray), 500, (item, callback) => {
// do other things that use native promises.
}, (error) => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
Jak widać, nie mogę zadeklarować myFunction
funkcji jako asynchronicznej, ponieważ nie mam dostępu do wartości wewnątrz drugiego wywołania zwrotnego eachLimit
funkcji.
javascript
node.js
asynchronous
async-await
Alexis Tyler
źródło
źródło
Odpowiedzi:
Efektywnie korzystasz z obietnic wewnątrz funkcji wykonawczej konstruktora obietnicy, więc jest to wzorzec anty-wzorca konstruktora Promise .
Twój kod jest dobrym przykładem głównego ryzyka: nie propaguje bezpiecznie wszystkich błędów. Przeczytaj, dlaczego tam .
Ponadto użycie
async
/await
może sprawić, że te same pułapki będą jeszcze bardziej zaskakujące. Porównać:let p = new Promise(resolve => { ""(); // TypeError resolve(); }); (async () => { await p; })().catch(e => console.log("Caught: " + e)); // Catches it.
z naiwnym (złym)
async
odpowiednikiem:let p = new Promise(async resolve => { ""(); // TypeError resolve(); }); (async () => { await p; })().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
Poszukaj ostatniego w konsoli internetowej przeglądarki.
Pierwsza z nich działa, ponieważ każdy natychmiastowy wyjątek w funkcji wykonawczej konstruktora Promise wygodnie odrzuca nowo skonstruowaną obietnicę (ale wewnątrz każdej
.then
jesteś sam).Drugi nie działa, ponieważ każdy natychmiastowy wyjątek w
async
funkcji odrzuca niejawną obietnicę zwróconą przezasync
samą funkcję .Ponieważ wartość zwracana funkcji wykonawcy konstruktora obietnicy nie jest używana, to zła wiadomość!
Twój kod
Nie ma powodu, dla którego nie możesz zdefiniować
myFunction
jakoasync
:async function myFunction() { let array = await getAsyncArray(); return new Promise((resolve, reject) => { eachLimit(array, 500, (item, callback) => { // do other things that use native promises. }, error => { if (error) return reject(error); // resolve here passing the next value. }); }); }
Chociaż po co używać przestarzałych bibliotek kontrolnych współbieżności, skoro tak jest
await
?źródło
return await
:return new Promise
wystarczy.Zgadzam się z odpowiedziami podanymi powyżej, a mimo to czasami lepiej jest mieć asynchroniczność w obietnicy, zwłaszcza jeśli chcesz połączyć kilka operacji zwracających obietnice i uniknąć
then().then()
piekła. Rozważałbym użycie czegoś takiego w tej sytuacji:const operation1 = Promise.resolve(5) const operation2 = Promise.resolve(15) const publishResult = () => Promise.reject(`Can't publish`) let p = new Promise((resolve, reject) => { (async () => { try { const op1 = await operation1; const op2 = await operation2; if (op2 == null) { throw new Error('Validation error'); } const res = op1 + op2; const result = await publishResult(res); resolve(result) } catch (err) { reject(err) } })() }); (async () => { await p; })().catch(e => console.log("Caught: " + e));
Promise
konstruktora nie jest asynchroniczna, więc lintery nie wyświetlają błędów.await
.Wadą jest jednak to, że trzeba pamiętać o zakładaniu
try/catch
i mocowaniu goreject
.źródło
static getPosts(){ return new Promise( (resolve, reject) =>{ try { const res = axios.get(url); const data = res.data; resolve( data.map(post => ({ ...post, createdAt: new Date(post.createdAt) })) ) } catch (err) { reject(err); } }) }
remove await, a async rozwiąże ten problem. ponieważ zastosowałeś obiekt Promise, to wystarczy.
źródło
axios.get(url)
działał tak, jakby został nazwany jakoawait axios.get(url)
?