Trying to learn some modern JS and in particular the ECMAScript 6 Promises. I'm playing with this simple test:
let slow = new Promise((resolve) => {
setTimeout(function()
{
console.log('slow');
resolve();
}, 2000, 'slow');
});
let instant = new Promise((resolve) => {
console.log('instant');
resolve();
});
let quick = new Promise((resolve) => {
setTimeout(function()
{
console.log('quick');
resolve();
}, 1000, 'quick');
});
Promise.all([slow, instant, quick]).then(function(results) {
console.log('finished');
}, function(error) {
console.log(error);
});
What I want here is to start all Promises async at the same time. And log when they are all finished. In the console this shows as expected: "instant", "quick", "slow" and "finished".
However what if I wanted to be sure that "instant" doesn't echo/log before "slow" has completed? That is, I want the console to log "quick", "slow", "instant" and "finished"...but at the same time, they must still all start at the same time async.
How can I achieve this?
So to be clear, what you want to do here is kick off all the promises at once and display the results of each promise in a particular order as they come in, correct?
In that case, I'd probably do it like this:
let slow = new Promise((resolve) => {
setTimeout(function()
{
// Rather than log here, we resolve to the value we want to log
resolve('slow');
}, 2000, 'slow');
});
let instant = new Promise((resolve) => {
resolve('instant');
});
let quick = new Promise((resolve) => {
setTimeout(function()
{
resolve('quick');
}, 1000, 'quick');
});
// All Promises are now running. Let's print the results...
// First wait for the result of `slow`...
slow.then((result) => {
// Result received...
console.log(result);
// Now wait for the result of instant...
instant.then((result) => {
// Result received...
console.log(result);
// Now wait for the result of quick...
quick.then((result) => {
// Result received...
console.log(result);
}).then((result) => {
// Done
console.log('finished');
});
});
});
Notice that unlike cchamberlain's answer, this method does not wait for all promises to resolve before it starts returning results. It returns the results as they come in, but without violating your requirement of keeping the results in-order. (To verify this, try changing the wait time of quick
to 2500ms, and observe that its result is printed 500ms after instant
.) Depending on your application, this may be desirable.
The above code is a bit messy, but thankfully with the new async/await
syntax in ES2017 it can be made much cleaner:
let slow = new Promise((resolve) => {
setTimeout(function()
{
// Rather than log here, we resolve to the value we want to log
resolve('slow');
}, 2000, 'slow');
});
let instant = new Promise((resolve) => {
resolve('instant');
});
let quick = new Promise((resolve) => {
setTimeout(function()
{
resolve('quick');
}, 1000, 'quick');
});
// All Promises are now running. Let's print the results...
async function logResults(...promises) {
for (let promise of promises) {
console.log(await promise);
}
}
logResults(slow, instant, quick).then(() => console.log('finished'));
Try in Babel. Note: The above code doesn't currently work in modern browsers without Babel (as of October 2016). In future browsers it will.
Part of the issue is the logging is happening in the setTimeout
method, and not actually from the promise resolution.
const slow = new Promise((resolve) => {
setTimeout(() => {
console.log('slow - from setTimeout');
resolve('slow - from resolve');
}, 2000, 'slow');
});
const instant = new Promise((resolve) => {
console.log('instant - from setTimeout');
resolve('instant - from resolve');
});
const quick = new Promise((resolve) => {
setTimeout(() => {
console.log('quick - from setTimeout');
resolve('quick -from resolve');
}, 1000, 'quick');
});
Promise.all([slow, instant, quick]).then((results) => {
console.log(results);
console.log('finished');
}, (error) => {
console.log(error);
});
Passing in the value to the resolve
method will return everything in the Promise.all
. The response comes back from each promise as an array, and you can iterate through those responses once all are complete.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With