Promise.then's "onFulfilledHandler" is called asynchronously. Meaning the callback will enter the queue for immediate execution after current stack fully unraveled. Calling 1000 then's takes a few milliseconds:
function f(x) {
if (x > 0) {
return Promise.resolve(--x).then(f);
}
console.timeEnd('f');
}
console.time('f');
f(1000);