开发者

Returning a variable from closure

How can I get the return value of that.whatever back from the closure? Instead of:

this.setCanvas = function(files){
  var numItems = files.length - 1;
  this.items = {};

  var i = 0;
  for(i=0;i<=numItems;i++)
  {
    var file = files[i];
    var reader = new FileReader(); 

    reader.onload = (function(i) { 
      return function(e) { 
        var something = that.whatever();
        items[i] = something;
      }; 
   开发者_JAVA技巧 })(i);  

    reader.readAsDataURL(file);
  }

console.log(items); 
}

I need items[i] defined. If I console.log items[i] outside of the closure it is undefined.


The problem isn't the closure; it's the callback. Whatever needs to use the value of that.whatever needs to be executed in the callback.


You can augment your code to keep track of the number of files loaded. This way, when the last file has been loaded, you can invoke an ultimate completion handler:

  this.setCanvas = function(files) {
    var numItems = files.length - 1;
    var itemsLoaded = 0; // Initialize to zero

    var items = [];

    var i = 0;
    for(i=0;i<=numItems;i++) {

      var file = files[i];
      var reader = new FileReader(); 

      reader.onload = (function(i) { 
        return function(e) { 
          var something = that.whatever();
          items[i] = something;

          if(++itemsLoaded == numItems) {
            // At this point all files will have been loaded.
            allLoaded();
          }
        }; 
      })(i);  

      reader.readAsDataURL(file);
    }

    function allLoaded() {
      // Now we can analyze the results
      console.log(items); 
    }
  }

I also changed items to be an Array instead of an Object.

Also if you want to be a little more clever, you could decrement numItems and check for zero instead of creating a new itemsLoaded variable.


There are a couple things you need to change here. First set this.items to an array. Next assign this to self so it can be referenced in the closure. Next assign the something to self.items[i] instead of items[i]. Finally use this.items in the console.log

this.setCanvas = function(files){
  var self = this;
  var numItems = files.length - 1;
  this.items = [];

  var i = 0;
  for(i=0;i<=numItems;i++)
  {
    var file = files[i];
    var reader = new FileReader(); 

    reader.onload = (function(i) { 
      return function(e) { 
        var something = that.whatever();
        self.items[i] = something;
      }; 
    })(i);  

    reader.readAsDataURL(file);
  }

    console.log(this.items); 
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜