I'm struggling to understand javascript promises. I have a simple list and I want to highlight each element in turn by adding an "active" class, with a pause between each.
So I have the following mark up -
<h2 class="step step1">Promise</h2>
<h2 class="step step2">Promise</h2>
<h2 class="step step3">Promise</h2>
<h2 class="step step4">Promise</h2>
and 2 javascript promises. First to set the step -
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);
})
}
and a second that implements a wait -
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
and then I'm trying to chain it all together like this -
wait(1000)
.then(function () { setStep(1) })
.then(wait(1000))
.then(function () { setStep(2) })
.then(wait(1000))
.then(function () { setStep(3) })
The first wait seem to execute as expected but then everything else appears to happen together and step 3 is highlighted, with no waits in between. The console messages all show the same timestamp.
What am I overlooking?
The complete code is as follows -
<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>
You need to pass a function reference to
.then()
, not a promise. So change this:to this:
or this:
.then()
only works properly when you pass it a function reference that it can call later. When you do.then(wait(1000))
, you're executingwait(1000)
immediately and passing the return value (a promise) to.then()
. That is not how.then()
works and you didn't want to be executingwait(1000)
immediately either.Or, you could make a new
waitFn()
that returns a function that could be used in the way you were doing (because it returns a function when called):Then, you could do this: