简体   繁体   English

Node.js Promise 链解析过早

[英]Node.js Promise chain resolving too early

There's something about chaining promises that I don't understand.有一些关于链接承诺的事情我不明白。 The Node.js snippet below produces the following output.下面的 Node.js 片段生成以下 output。 Why is promise.allSettled called after the first sleep on line 18 and not after the 2nd one on line 21?为什么promise.allSettled在第 18 行的第一次sleep后调用,而不是在第 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.因为您还没有解决 promise 创建的sleep(i).then .then 到 promise 从第二次sleep ,所以它不会等待第二次操作完成后再稳定。 You need a return in front of the second call:您需要在第二次调用之前return

 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:sleepsleep串行操作拆分为自己的 function 可能更清楚,也许是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.问题是 Promise.allSettled 并行运行所有承诺,因此所有承诺同时解决。 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM