0

I'm a bit confused in a situation,
given the sample code here where I'm loading several urls, and connected the event Listener:

var pages= Array();
var loading= Array();

for(i=0; i < urls.length; i++){
var page =new WebPage(urls[i]);

   page.onLoadStarted = function() {
       loading[i]= true;
       console.log('Loading started');
   };    
   pages[i]=page;

}

I have 5 urls, and I get 5 times "Loading started" in the console output, however the loading array had only one value defined (true) all the rest are "undefined"; Looks like when the event is triggered loading[i]= true; uses the last value of I to access the array instead of using its address. How can I fix that ?

I've tried adding a property to the page object, but same thing happens;

Here is what I've tried:

var pages= Array();

for(i=0; i < urls.length; i++){
var page =new WebPage(urls[i]);

   page.onLoadStarted = function() {
       page.loading= true;
       console.log('Loading started');
   };    
   pages[i]=page;

}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Xsmael
  • 3,624
  • 7
  • 44
  • 60
  • Just use `for(let i=0;...)` or wrap the event handler in an IIFE, if you can't rely on ES2015 –  Jun 28 '16 at 17:12

2 Answers2

1

If onLoadStarted is an event handler then the for loop is executed much faster than the all the event handlers. In that time i is 5 and during each function call, the sixth index of the array is populated with a true value. As the lower indices of array do no have any set value you get such output.

One option is using the Array.prototype.forEach or Array.prototype.map method. Both functions take a function as the handler. The handler which is a function, creates a new scope and remembers the defined values.

urls.forEach(function(url /* element */, i /* index */) {
   var page = new WebPage(url);

   page.onLoadStarted = function() {
       loading[i]= true;
       console.log('Loading started');
   };    
   pages[i]=page;
}) 
Ram
  • 143,282
  • 16
  • 168
  • 197
  • yea, i ended up understanding that, but why is my 2nd attempt(code) didn't work as well ? i din't use any index; but linked to the object it self as a property, and later when i check all pages for that property, same thing only one is define and has true value. i would really like to understand that. – Xsmael Jun 28 '16 at 18:13
1

Try with this code (es6)

    let pages = Array();
    urls.map((url,i) =>{
     let page = new WebPage(urls[i]);

     page.onLoadStarted(() =>{
      loading[i] = true;
      console.log('Loading started');
     })

(es5)

    var pages = Array();
    urls.map(function(url,i){
     var page = new WebPage(urls[i]);

     page.onLoadStarted(function(){
      loading[i] = true;
      console.log('Loading started');
     })
Rui Costa
  • 800
  • 4
  • 13