为什么 promise 在循环中的工作方式不同?

Why promises work differently in loops?

我有 delay 函数生成器用于 Promise.then 方法

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

当我使用没有循环的 delay 函数时它工作正常:

var promise = Promise.resolve();
promise
    .then(() => console.log(1))
    .then(delay(1000))
    .then(() => console.log(2))
    .then(delay(1000))
    .then(() => console.log(3))
    .then(delay(1000));

但是当我在循环中使用它时,所有数字都被毫无延迟地打印出来:

var loopPromise = Promise.resolve();
for (let i = 1; i <= 3; i++) {
    loopPromise
        .then(() => console.log(i))
        .then(delay(1000));
}

为什么 promise 在循环中的工作方式不同?我该如何解决这个循环行为?

Why promises work differently in loops?

如果我们展开循环版本,您就是这样做的:

var loopPromise = Promise.resolve();

loopPromise
    .then(() => console.log(1))
    .then(delay(1000));

loopPromise
    .then(() => console.log(2))
    .then(delay(1000));

loopPromise
    .then(() => console.log(3))
    .then(delay(1000));

IE 中的每个调用都直接进入 loopPromise 并立即被调用,而不是被链接起来。

How i can fix this loop behavior?

最简单的方法是通过覆盖原始 Promise 变量来跟踪每次迭代中链的最新部分:

var loopPromise = Promise.resolve();
for (let i = 1; i <= 3; i++) {
    loopPromise = loopPromise
        .then(() => console.log(i))
        .then(delay(1000));
}