For example I found some api library that is based on promises, and I need to issue api requests using this library in some interval, infinite times (like usual back-end loop). This api requests - actually chain of promises.
So, if I write function like:
function r(){
return api
.call(api.anotherCall)
.then(api.anotherCall)
.then(api.anotherCall)
...
.then(r)
}
Will it cause stack overflow?
Solutions that I come up with is to use setTimeout for a call of r
recursively.
function r(){
return api
.call(api.anotherCall)
.then(api.anotherCall)
.then(api.anotherCall)
.then(()=>{setTimeout(r, 0)})
}
So setTimeout will call r
actually only when call stack is empty.
Is it good solution, or there is some standard way of calling promises recursively?
No, it will not. Per the promise specification,
.then()
waits for the stack to completely unwind and is then called after the stack is clear (essentially on the next tick of the event loop). So,.then()
is already called asynchronously after the current event is done processing and the stack is unwound. You do not have to usesetTimeout()
to avoid stack build-up.Your first code example will not have any stack build-up or stack overflow, no matter how many times you repeat it.
In the Promises/A+ specification, section 2.2.4 says this:
And, "platform code" is defined here in 3.1:
The ES6 promise specification uses different words, but generates the same effect. In ES6, promise
.then()
is performed by enqueing a job and then letting that job get processed and the job only gets processed when no other code is running and the stack is empty.This is how running such as job is described in the ES6 spec: