How to chain functions with delays. I tried the following:
Promise.resolve()
.then(setKeyframe('keyframe-0'))
.then(delay(3000))
.then(setKeyframe('keyframe-1'))
.then(delay(3000))
.then(setKeyframe('keyframe-2'))
;
function delay(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
function setKeyframe (name) {
var element = document.getElementsByClassName('animation-container')[0];
element.className = 'animation-container ' + name;
}
All functions seem to be called immediately after each other. The delay function does not delay the chain. What am I missing?
How to chain functions with delays. I tried the following:
Promise.resolve()
.then(setKeyframe('keyframe-0'))
.then(delay(3000))
.then(setKeyframe('keyframe-1'))
.then(delay(3000))
.then(setKeyframe('keyframe-2'))
;
function delay(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
function setKeyframe (name) {
var element = document.getElementsByClassName('animation-container')[0];
element.className = 'animation-container ' + name;
}
All functions seem to be called immediately after each other. The delay function does not delay the chain. What am I missing?
Share Improve this question edited Mar 3, 2017 at 17:32 jib 42.6k17 gold badges108 silver badges165 bronze badges asked Apr 14, 2016 at 15:39 SvenSven 6,33824 gold badges77 silver badges116 bronze badges 2-
4
You have to pass a callback that returns a promise into
then
, not a promise itself. – Bergi Commented Apr 14, 2016 at 15:41 - you're starting all of the actions at once – Kevin B Commented Apr 14, 2016 at 15:42
3 Answers
Reset to default 5Your mistake might be easier to spot with a function without arguments:
The right way:
Promise.resolve().then(setFirstKeyframe)
Above, the function setFirstKeyframe
is an argument to .then
, for the promise to call later.
The wrong way:
Promise.resolve().then(setFirstKeyframe())
Here, setFirstKeyframe
is called immediately (!), and its result (a promise) is passed to then
(which gets ignored as then
expects a function).
For functions with arguments use an anonymous function:
Promise.resolve().then(function() {
return setFirstKeyframe('keyframe-0');
})
This is where es6 arrow functions rock:
Promise.resolve().then(() => setFirstKeyframe('keyframe-0'))
.then()
accepts a function, which may or may not return a promise
You are however passing a promise directly
// Yes
Promise.resolve().then(() => { return new Promise(); });
// No
Promise.resolve().then(new Promise());
It's because you were calling all functions instead of providing them as handlers.
Promise.resolve('keyframe-0')
.then(setKeyframe)
.then(delay(3000, 'keyframe-1'))
.then(setKeyframe)
.then(delay(3000, 'keyframe-2'))
.then(setKeyframe)
;
function delay(ms, value) {
return function (val) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, value !== undefined ? value : val);
});
};
}
function setKeyframe(name) {
var element = document.body;
element.className = 'animation-container ' + name;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.keyframe-0 { background: red; }
.keyframe-1 { background: green; }
.keyframe-2 { background: blue; }