async
/await
are great, but they're not a 100% replacement for all promise-using code. Sometimes (eg. when you need to use Promise.all
) you do need to use the promises as values themselves, and not used secretly inside async
/await
.
There are ways to avoid doing that, like eschewing the ES6 map
and other array iteration methods, and instead using for
loops ... but usually doing that is ... well the cure is worse than the illness. Just use promises.
EDIT:
Here's a basic example based on comment feedback. Let's say you have two (or more) URLs, and want to fetch the first one THEN (after it returns), fetch the next one, and once they're ALL fetched do something else. If you try to do that synchronously with ES6 array methods, even if you use async
/await
, it won't work:
const urls = ['www.example.com/1', 'www.example.com/2'].
var promises = urls.map(async url => await fetch(url));
Promise.all(promises).then(doSomethingElse);
What that code will actually do is immediately fetch all the URLs; it won't wait to fetch the second until the first is done.
To do that you could use async
/await
with a for
loop and avoid the ES6 stuff (presumably the following is inside an async
function):
const urls = ['www.example.com/1', 'www.example.com/2'].
const pageHtml = [];
for (var i = 0; i < promises.length; i++) {
const url = urls[i];
const html = await fetch(url));
pageHtml.push(html);
}
doSomethingElse(); // no need for Promise.all!
... but then you're using for
loops like it's 1999; ick! The better solution in my opinion is to use modern Javascript, but just don't use async
/await
for everything.
Use those keywords most of the time, but then when you need to use Promise.all
either use a recursive function (if you need the "fetch #1 AFTER #2" part; see @jcubic's answer for a possible implementation), or if you don't just do:
const urls = ['www.example.com/1', 'www.example.com/2'].
var promises = urls.map(fetch);
Promise.all(promises).then(doSomethingElse);
Yes you are avoiding async
/await
and using an array or Promise objects
directly with Promise.all
... but the code is short and clear and does what you want. You don't have to always use those keywords.