2012-03-08 53 views
0

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

是''loadArrFromFile'的SomeClass.prototype'一员?顶部的代码表明它是,但我看到的唯一任务是'extfoo.loadArrFromFile'。同时请记住,'this'的值将在'xhr.onreadystatechange'回调中发生变化,因此'this.someObjVar = xhr.resp ...'不会与直接位于'loadArrFromFile '功能。 – 2012-03-08 15:02:51

回答

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 ... 
}; 

有几种方法来解决这个问题,但进行测试,尝试将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.someObjVar应该是从extfoo.someObjVar不同?如果是这种情况,此代码将起作用,但除此之外,您需要在每个引用之间包含SomeClass

+0

你说得对,但是如何将引用传递给当前的someClass实例? – User 2012-03-08 14:59:36

+0

用解决方案更新了答案 – 2012-03-08 15:03:48

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(); 
}); 
+0

是的,除了问题陈述'//在引用showSomeObjVar()'的异步返回后很久以后会被调用“,所以如果这是相信的话,则异步问题将会是覆盖。 – 2012-03-08 15:01:02

+0

对不起,我在第一篇文章发布后一分钟后添加了该评论 – User 2012-03-08 15:02:00

+0

如果您的请求是indead异步,那么loadArrFromFile将在请求完成之前返回,因为javascript不是多线程的。所以当你做xhr.send()时,它不会等待来自服务器的响应,但会继续执行下面的代码。 onreadystatechange函数稍后会被调用(通过同一个线程)。 – 2012-03-09 06:19:08