承诺减少提前回报

时间:2016-12-15 01:19:34

标签: javascript node.js promise reduce

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!

1 个答案:

答案 0 :(得分:2)

。然后期望一个函数作为它的参数(onFullfilled, onRejected),任何不是函数的值完全忽略

但是,reduce回调中的prom是一个承诺,所以只有第一个承诺会被等待

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

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!'));

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

鉴于此,对于printDots来说,更好的解决方案是使用Promise.all

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

根据评论,承诺需要按顺序运行 - 这很简单,只需使用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)来减少,以便第一次迭代使用承诺,就像所有后续的承诺一样