Node.js Promise 链解决得太早
Node.js Promise chain resolving too early
关于链接承诺,我有些不明白。下面的 Node.js 片段产生以下输出。为什么 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();
因为您还没有将创建的承诺 sleep(i).then
解析为第二个 sleep
的承诺,所以它不会等待第二个操作完成就可以解决。您需要在第二个电话前加一个 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();
这是一个有两个周期的版本,睡眠调用标记得更清楚:
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();
将 sleep
、sleep
串行操作拆分成它自己的函数可能会更清楚,也许是 async
函数:
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();
问题是 Promise.allSettled 运行 所有的承诺都是并行的,所以它们都是同时解决的。如果你想运行他们一一尝试
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();
关于链接承诺,我有些不明白。下面的 Node.js 片段产生以下输出。为什么 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();
因为您还没有将创建的承诺 sleep(i).then
解析为第二个 sleep
的承诺,所以它不会等待第二个操作完成就可以解决。您需要在第二个电话前加一个 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();
这是一个有两个周期的版本,睡眠调用标记得更清楚:
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();
将 sleep
、sleep
串行操作拆分成它自己的函数可能会更清楚,也许是 async
函数:
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();
问题是 Promise.allSettled 运行 所有的承诺都是并行的,所以它们都是同时解决的。如果你想运行他们一一尝试
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();