0

Here I'm trying to Log value of a to console.

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() {
            driver.sleep(1000).then(function() {
                console.log(a[i]);
            })
        });
    }
});

Result of given code is:
Undefined
Undefined
Undefined
Undefined

josh
  • 9,656
  • 4
  • 34
  • 51
Pawan Juyal
  • 251
  • 1
  • 5
  • 14

3 Answers3

0

You shouldn't create function inside the loop - use "forEach" instead: ("driver" object created to simulate real promise behavior)

var driver = {}
driver.sleep = function() {
return new Promise((resolve)=>{
  resolve()
})
}

driver.sleep(2000).then(function(){
var a = ["Quas","Wex","Exort","Invoke"];
    a.forEach((b)=>{
        driver.sleep(1000).then(function loggingA(){
        driver.sleep(1000).then(function(){
        console.log(b);})
        });
    })
});
Michał Sałaciński
  • 2,256
  • 1
  • 11
  • 10
0

It can access the function. That the reason it generate "undefined" rather than an error when accessing a[i].

The bug of the code is, when accessing variable i, it was incremented already 4. As a result, a[4] is undefined.

Dennis C
  • 24,511
  • 12
  • 71
  • 99
0

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.

josh
  • 9,656
  • 4
  • 34
  • 51