Javascript OOP-在异步回调中丢失了这一点
Javascript OOP - lost this in asynchronous callback
我在js-op上遇到了一个问题,这个问题仍然困扰着我——我确信我做得很糟糕,但我不知道如何做对。
例如,我有这个代码
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token);
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
问题是我无法从"request.onloadend"函数的上下文访问函数setToken,这可能是因为我丢失了对"this"的引用。
这个问题的解决办法是什么?我能以某种方式将"this"var传递给这个函数的上下文吗?
谢谢!
有几种方法可以做到这一点。最直接的方法是简单地保存您需要的值的副本:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
var self = this; // save "this" value
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
self.setToken(token); // use saved "this" value
self.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
另一种方法是使用bind
:
request.onloadend = (function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token); // use saved "this" value
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}).bind(this);
第二种方法是"更干净",但它存在浏览器兼容性问题(IE<9不支持它)。
.bind
函数:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
this.setToken(token);
this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}.bind(this); //<-- bound
}
您只需在外部范围中捕获对它的引用,我使用了标识符self
,但请随意赋予名称更语义的含义:
var self = this;
request.onloadend = function () {
...
self.setToken(token);
...
};
回调前捕获this
:
Auth.prototype.auth = function () {
var self = this;
var request = new XMLHttpRequest();
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
self.setToken(token);
self.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
将this
保存在回调之外的本地var中。
Auth.prototype.auth = function () {
var request = new XMLHttpRequest();
var _this = this;
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
_this.setToken(token);
_this.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
您说得很对:回调是以XMLHTTPRequest
对象作为上下文(即this
的值)调用的。你需要给你的实例另一个名称,这样你就可以在回调的范围内访问它:
Auth.prototype.auth = function () {
var request = new XMLHttpRequest(),
authInstance = this;
request.open('GET', this.getAuthServerURL() + '/token', true);
request.send();
request.onloadend = function () {
var response = JSON.parse(request.responseText);
console.log(response);
if(response.result == 'found') {
var token = response.token;
authInstance.setToken(token);
authInstance.isSigned = true;
} else {
console.log('Not logged yet.');
}
}
}
请参阅另一个问题的答案,了解为什么需要这样做的更多解释。我使用了authInstance
而不是self
,因为我认为使用描述性变量名通常是好的;你永远不需要弄清楚authInstance
的意思,而当将来有人(可能是你!)读到代码时,self
可能会含糊不清。
另一种选择是使用bind
,但这可能比必要时更复杂。
相关文章:
- 为什么(如何)'这'从函数内部调用回调时发生更改
- 原型回调函数替换'这'价值
- 如何绑定'这'到react类之外的函数,后者是来自其他组件的回调
- Javascript OOP-在异步回调中丢失了这一点
- 一根绳子可以有回文吗,有没有更好的方法可以做到这一点
- 在 Backbone 中.js事件回调这是什么,以及如何访问触发的元素
- 这真的是从事件回调中获取 Rx.Observable 的最佳方式吗?
- 更新'这'当返回用.apply()调用的函数时,从回调
- Javascript闭包:Phonegap和'这'在回调中
- 访问'这'promise回调中的对象(然后)
- 什么'这是停止递归回调的最佳方法
- 这是JavaScript/jQuery回调的正确方式吗
- 如何通过'这'转换为setTimeout回调
- 如何使用'这'在jQuery插件回调中
- 这是糟糕的回调练习
- 为什么我的回调中的这段代码在页面加载时执行
- 这有什么不对吗?尝试在原型中使用请求回调,但收效甚微
- 这是不好的做法,以影子变量的回调
- 如何在Node.js和Express.js中改进这段代码,避免回调地狱
- 关于'这'在node.js的回调中