I'm trying to convert some of my code to promises, but I can't figure out how to chain a new promise inside a promise.
My promise function should check the content of an array every second or so, and if there is any item inside it should resolve. Otherwise it should wait 1s and check again and so on.
function get(){
return new Promise((resolve) => {
if(c.length > 0){
resolve(c.shift());
}else{
setTimeout(get.bind(this), 1000);
}
});
}
let c = [];
setTimeout(function(){
c.push('test');
}, 2000);
This is how I expect my get() promise function to work, it should print "test" after 2 or 3 seconds max:
get().then((value) => {
console.log(value);
});
Obviously it doesn't work, nothing is ever printed
In the
else
case, you never resolve that promise.get
might create another one, but it is returned to nowhere.You should promisify your asynchronous function (
setTimeout
) on the lowest level, and then only chain your promises. Byreturn
ing the result of the recursive call from athen
callback, the resulting promise will resolve with the same result:The problem is that your recursive call doesn't pass the
resolve
function along, so theelse
branch can never callresolve
.One way to fix this would be to create a closure inside the promise's callback so that the recursive call will have access to the same
resolve
variable as the initial call toget
.setTimeout
has terrible chaining and error-handling characteristics on its own, so always wrap it:While you didn't ask, for the benefit of others, this is a great case where
async
/await
shines:Note how we didn't need
Promise.resolve()
this time, sinceasync
functions do this implicitly.Use
setInterval
to check every second. Run this script to understand.What you need is a polling service, which checks periodically for specific condition prior proceeding with promise resolution. Currently when you run
setTimeout(get.bind(this), 1000);
you are creating a new instance of the promise without actually resolving the initial promise, because you don't reference to the initialresolve
function that you created.Solution:
resolve
&reject
as params in the setTimeout invocation e.g.setTimeout(HandlePromise, 1000, resolve, reject, param3, param4 ..);
setTimeout API