The problem is that, because driver.sleep
is a promise, it runs after i
has been incremented past the length of a
. That is, by the time the promises run, i
is 4
, which is not a valid index in a
. You can get around this by doing one of two things (adding a driver mock as well):
1: Bind i
to the outermost function inside of the for
loop:
var driver = {
sleep: function(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}
}
driver.sleep(2000).then(function logAInConsole() {
var a = ["Quas","Wex","Exort","Invoke"];
for(var i = 0; i < a.length; i++) {
driver.sleep(1000).then(function loggingA(i) {
driver.sleep(1000).then(function() {
console.log(a[i]);
})
}.bind(this, i));
}
});
2: Use forEach
:
var driver = {
sleep: function(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}
}
driver.sleep(2000).then(function logAInConsole() {
var a = ["Quas","Wex","Exort","Invoke"];
a.forEach(function(value) {
driver.sleep(1000).then(function loggingA(i) {
driver.sleep(1000).then(function() {
console.log(value);
})
});
});
});
In general, if you don't need to change anything in a
, it makes more sense to use forEach
, since it's generally more clear than a for loop at the cost of a tiny bit of performance. If you absolutely need a
and i
for some reason, or if you need the looping to be lazy, the only way to ensure that they are available in the promise functions is to bind them to the outermost function, preserving their value.