There's something about chaining promises that I don't understand. The Node.js snippet below produces the following output. Why is promise.allSettled
called after the first sleep
on line 18 and not after the 2nd one on line 21?
Cycle 0 is going to sleep promise.js:2
Cycle 0 slept for 2 seconds promise.js:6
Returned from sleep function promise.js:19
Cycle 0 is going to sleep promise.js:2
Done with the process promise.js:27
Cycle 0 slept for 2 seconds promise.js:6
function sleep(cycle) { console.log(`Cycle ${ cycle } is going to sleep`); return new Promise(resolve => { setTimeout(() => { console.log(`Cycle ${ cycle } slept for 2 seconds`); resolve(); }, 2000); }); } function process() { let cycles = 1; let subprocesses = []; for (let i = 0; i < cycles; i++) { subprocesses.push( sleep(i).then(() => { console.log('Returned from sleep function'); sleep(i); }) ); } Promise.allSettled(subprocesses).then(results => { console.log('Done with the process'); }); } process();
Because you haven't resolved the promise created sleep(i).then
to the promise from the second sleep
, so it doesn't wait for that second operation to finish before settling. You need a return
in front of the second call:
function sleep(cycle) { console.log(`Cycle ${ cycle } is going to sleep`); return new Promise(resolve => { setTimeout(() => { console.log(`Cycle ${ cycle } slept for 2 seconds`); resolve(); }, 2000); }); } function process() { let cycles = 1; let subprocesses = []; for (let i = 0; i < cycles; i++) { subprocesses.push( sleep(i).then(() => { console.log('Returned from sleep function'); return sleep(i); // <============================ }) ); } Promise.allSettled(subprocesses).then(results => { console.log('Done with the process'); }); } process();
Here's a version with two cycles, and with the sleep calls more clearly marked:
function sleep(cycle, sub) { console.log(`Cycle ${cycle}(${sub}) is going to sleep`); return new Promise(resolve => { setTimeout(() => { console.log(`Cycle ${cycle}(${sub}) slept for 2 seconds`); resolve(); }, 2000); }); } function process() { let cycles = 2; let subprocesses = []; for (let i = 0; i < cycles; i++) { subprocesses.push( sleep(i, "a").then(() => { console.log(`Returned from sleep function (${i})`); return sleep(i, "b"); // <============================ }) ); } Promise.allSettled(subprocesses).then(results => { console.log('Done with the process'); }); } process();
It might be clearer to split that sleep
, sleep
serial operation off into its own function, perhaps an async
function:
async function twoSleep(i) {
await sleep(i, "a");
console.log(`Returned from sleep function (${i})`);
await sleep(i, "b");
}
function process() {
let cycles = 2;
let subprocesses = [];
for (let i = 0; i < cycles; i++) {
subprocesses.push(twoSleep(i));
}
Promise.allSettled(subprocesses).then(results => {
console.log('Done with the process');
});
}
function sleep(cycle, sub) { console.log(`Cycle ${cycle}(${sub}) is going to sleep`); return new Promise(resolve => { setTimeout(() => { console.log(`Cycle ${cycle}(${sub}) slept for 2 seconds`); resolve(); }, 2000); }); } async function twoSleep(i) { await sleep(i, "a"); console.log(`Returned from sleep function (${i})`); await sleep(i, "b"); } function process() { let cycles = 2; let subprocesses = []; for (let i = 0; i < cycles; i++) { subprocesses.push(twoSleep(i)); } Promise.allSettled(subprocesses).then(results => { console.log('Done with the process'); }); } process();
The issue is that Promise.allSettled runs all promises in parallel, so all of them resolve at the same time. If you want to run them one by one try
async function process() {
const cycles = 1;
for (let i = 0; i < cycles; i++) {
await sleep(i).then(() => {
console.log("Returned from sleep function");
return sleep(i);
});
}
console.log("Done with the process");
}
process();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.