如何从异步回调中设置对象变量

时间:2012-03-08 14:49:59

标签: javascript asynchronous

我刚开始在javascript中创建自定义对象。我想使用下面的代码设置this.someObjVar,但我的方法有问题。也许异步响应使用它自己的范围或线程。

// The code below used like:
someClass = new extfoo.SomeClass();
someClass.loadArrFromFile();
// this will be called far later after async returns
someClass.showSomeObjVar();

extfoo.js
=========
var extfoo = {};

extfoo.SomeClass = function() {
  this.someObjVar = [];
  this.showSomeObjVar = extfoo.showSomeObjVar;
  this.loadArrFromFile = extfoo.loadArrFromFile;
};
// Bad results here
extfoo.showSomeObjVar = function() {
  // results '0'
  console.log('showSomeObjVar: ' + this.someObjVar.length);
};

// Async array population
extfoo.loadArrFromFile = function() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      this.someObjVar = xhr.responseText.split('\r\n')
      // results '23' elements
      console.log("someObjVar length: "+this.someObjVar.length);
    }
  }
  // request code ...
};

2 个答案:

答案 0 :(得分:0)

您确定this.someObjVar引用了extfoo吗?

this函数中的extfoo.loadArrFromFile对象有可能引用函数本身(xhr.onreadystatechange),而不是extfoo对象:

extfoo.loadArrFromFile = function() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {

      //I'm going to create a new variable for this function called this.someObjVar
      //Cause I don't know about extfoo's.
      this.someObjVar = xhr.responseText.split('\r\n')
      // results '23' elements
      console.log("someObjVar length: "+this.someObjVar.length);

      //Whup, end of the line, I guess I'll just forget about that variable I just made.
    }
  }
  // request code ...
};

有几种方法可以解决此问题,但要进行测试,请尝试将this函数中的extfoo.loadArrFromFile更改为extfoo

以下是修复方法:

extfoo.loadArrFromFile = function() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {

      //OOOH you mean that object
      extfoo.someObjVar = xhr.responseText.split('\r\n')
      // results '23' elements
      console.log("someObjVar length: "+extfoo.someObjVar.length);

    }
  }
  // request code ...
};

最后一件事...... extfoo.SomeClass.someObjVar应该与extfoo.someObjVar不同吗?如果是这种情况,此代码将起作用,否则,您将希望在每个引用之间包含SomeClass

答案 1 :(得分:0)

因为它是一个异步请求,someClass.loadArrFromFile()不会等到请求完成,所以someClass.showSomeObjVar()将在它完成之前被调用。

您可以添加终止处理程序来处理结果:

extfoo.loadArrFromFile = function(done) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      this.someObjVar = xhr.responseText.split('\r\n')
      // results '23' elements
      console.log("someObjVar length: "+this.someObjVar.length);
      done();
    }
  }

然后你可以这样做:

someClass.loadArrFromFile(function() {
  someClass.showSomeObjVar();
});