Below is a simple recursive function that takes in a length, and decrements it using setTimeout
. Once the length is <=
0, it's done.
How can I write this function (in pure JavaScript) so that I can use it like so:
animate(999).then(...)
const animate = length => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return
}
setTimeout(() => {animate(length)}, 10)
}
animate(999)
Update:
This is what I've tried. The problem I'm having is that it seems resolve
is either not being called, or is being called on a different promise.
const animate = length => {
return new Promise((resolve, reject) => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
resolve(true)
return // without this the function runs forever
}
setTimeout(() => {animate(length)}, 10)
})
}
animate(999).then(result => console.log(result))
** Working Update (but don't understand it) **
const animate = length => {
return new Promise((resolve, reject) => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return resolve(true)
}
setTimeout(() => {resolve(animate(length))}, 10)
})
}
animate(999).then(result => console.log(result))
setTimeout(() => {animate(length)}, 10)
will not work, this might call the animate
function again but never resolve the promise created in the outermost invocation (this is what your "working update" fixes - it resolves the outer promise with the promise from the recursive call, which will cause them to fulfill with the same result).
Instead of messing around with callbacks that much, promisify the asynchronous primitive that you are using, setTimeout
:
function wait(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}
and then use that in your animation function to always return a promise:
const animate = length => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return Promise.resolve()
}
return wait(10).then(() => {
return animate(length)
})
}
A new Promise
and consequently its resolve
and reject
is being generated every time, because you are returning a new Promise
on every setTimeout
function call and only resolving the latest one (the one inside the if (length <= 0)
).
If you had placed the Promise((resolve, reject)
over the function it would have worked fine.
Either that or you carry the resolve, reject
with you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With