javascript promise chain不等待先前的承诺执行

时间:2018-03-10 08:38:30

标签: javascript promise

我很难理解javascript的承诺。我有一个简单的列表,我想通过添加一个“活动”类来突出显示每个元素,每个元素之间有一个暂停。

所以我有以下标记 -

<h2 class="step step1">Promise</h2>
<h2 class="step step2">Promise</h2>
<h2 class="step step3">Promise</h2>
<h2 class="step step4">Promise</h2>

和2个javascript承诺。首先设置步骤 -

function setStep(step) {
    return new Promise(function (resolve, reject) {
        console.log("Step ", step, new Date())
        document.querySelectorAll('.step').forEach(function (match) {
            match.classList.remove("active");
        });

        document.querySelector(".step" + step).classList.add("active");
        resolve(step);
    })
}

和实现等待的第二个 -

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

然后我试图将它们全部链接在一起 -

wait(1000)
    .then(function () { setStep(1) })
    .then(wait(1000))
    .then(function () { setStep(2) })
    .then(wait(1000))
    .then(function () { setStep(3) })

第一次等待似乎按预期执行,但随后其他一切似乎一起发生,第3步突出显示,中间没有等待。控制台消息都显示相同的时间戳。

我在俯瞰什么?

完整的代码如下 -

<style>
    .active {
        background-color: #C00;
        color: #FFF;
    }
</style>

<h2 class="step step1">Step 1</h2>
<h2 class="step step2">Step 2</h2>
<h2 class="step step3">Step 3</h2>

<script>
  const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

  function setStep(step) {
    return new Promise(function (resolve, reject) {
        console.log("Step ", step, new Date())
        document.querySelectorAll('.step').forEach(function (match) {
            match.classList.remove("active");
        });

        document.querySelector(".step" + step).classList.add("active");
        resolve(step);
    })
}

  wait(1000)
    .then(function () { setStep(1) })
    .then(wait(1000))
    .then(function () { setStep(2) })
    .then(wait(1000))
    .then(function () { setStep(3) })
</script>

1 个答案:

答案 0 :(得分:4)

您需要将函数引用传递给.then(),而不是承诺。所以改变这个:

.then(wait(1000))

到此:

.then(wait.bind(null, 1000))

或者这个:

.then(() => wait(1000))

.then()仅在您向其传递一个稍后可以调用的函数引用时才能正常工作。执行.then(wait(1000))后,您立即执行wait(1000)并将返回值(承诺)传递给.then()。这不是.then()的工作原理,您也不想立即执行wait(1000)

或者,您可以创建一个新的waitFn(),它返回一个可以按照您的方式使用的函数(因为它在调用时返回一个函数):

function waitFn(t) {
    return function() { return wait(t);}
}

然后,你可以这样做:

wait(1000)
  .then(function () { setStep(1) })
  .then(waitFn(1000))
  .then(function () { setStep(2) })
  .then(waitFn(1000))
.  then(function () { setStep(3) })