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

How to set object variable from async callback

本文关键字:设置 对象 变量 回调 异步      更新时间:2023-09-26

我刚开始用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 ...
};

您确定this.someObjVar正在引用extfoo吗?

extfoo.loadArrFromFile函数中的this对象可能引用的是函数本身(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 ...
};

有几种方法可以解决此问题,但要进行测试,请尝试将extfoo.loadArrFromFile函数中的this更改为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.someObjVarextfoo.someObjVar应该不同吗?如果是这种情况,此代码将起作用,但除此之外,您将希望在每个引用之间包含一个SomeClass

由于这是一个异步请求,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();
});