减少承诺 returns 早

Reduced promise returns early

function timeout(delay) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, delay);
    });
}

function printDots(delays) {
    return delays.map((delay) => {
        return timeout(delay).then(() => process.stdout.write('.'))
    }).reduce((acc, prom) => acc.then(prom));
}

printDots([513, 3402, 1337, 4122]).then(() => process.stdout.write('DONE!'));

这会打印 .DONE!... 但我预计它会打印 ....DONE!

.then 期望一个函数作为参数 (onFullfilled, onRejected),任何不是函数的值都 完全 被忽略

然而,reduce回调中的prom是一个promise,所以只会等待第一个promise

简单的更改,下面标记的应该可以解决问题

function timeout(delay) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, delay);
    });
}

function printDots(delays) {
    return delays.map((delay) => {
        return timeout(delay).then(() => process.stdout.write('.'))
    }).reduce((acc, prom) => acc.then(() => prom));
    //                                ^^^^^^
}

printDots([513, 3402, 1337, 4122]).then(() => process.stdout.write('DONE!'));

但是请注意,promise 将在大约同一时间开始,不会在 1 开始之前等待 0 结束等

鉴于此,一个可以说是更好的 printDots 解决方案是使用 Promise.all

function printDots(delays) {
    return Promise.all(delays.map((delay) => timeout(delay).then(() => process.stdout.write('.'))));
}

As per comments, the promises need to run sequentially - that's as simple as only using reduce

function timeout(delay) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, delay);
    });
}

function printDots(delays) {
    return delays.reduce((acc, delay) => acc.then(() => timeout(delay).then(() => process.stdout.write('.'))), Promise.resolve());
}

printDots([513, 3402, 1337, 4122]).then(() => process.stdout.write('DONE!'));

在这种情况下,您需要提供一个初始承诺 (Promise.resolve) 来减少,以便第一次迭代使用一个承诺,就像所有后续的一样