Seems a bit convoluted, and almost silly to get promises involved on something that's ALREADY event (timeout) driven. More so that this just flat out isn’t something I’d use a for loop for.
A scope block, let, and a if statement would be far better IMHO.
{
let i = 0;
function step() {
console.log(i);
if (++i < 100) setTimeout(step, 1000);
}
setTimeout(step, 1000);
}
The wrapping block isolates the LET (one of the few times I’d even use LET), we tell the “side effect” pissers and moaners to sod right off and access that block scoped incrementor.
Easy-peasy, lemon squeezy.
Another possibility is to make a wrapping function. In that case I’d use the maximum loop count for efficiency sake, but I’m an assembly programmer. The idea of a “loop” that counts upward is wasteful and not how I think about problems.
function limitedTimeout(callback, delay, count) {
function actualCall() {
callback(--count);
if (count) setTimeout(actualCall, delay);
} // actualCall
setTimeout(actualCall, delay);
} // limitedTimeoutlimitedTimeout(function(count) {
console.log(99 - count);
}, 1000, 100);
To me promises are hard to follow cryptic spaghetti code. Just like how people are using the painfully cryptic arrow function trash, the over-use of let/const in places where all it does is add overhead, and the endless pointless callbacks for things that have ZERO reason to even get callbacks involved. (see such idiocy as Array.map or Array.forEach)
But what do I know? I seem to have radically different ideas of what clear, concise, legible, easy to maintain, easy to read, easy to follow code is. Probably because I started out hand coding machine language and spent a decade working in Ada. It gives you a radically different perspective from the tripe and bald faced lies the “C world” yums up.