如何将范围保持在 XHR 请求中?
How to keep scope within an XHR request?
所以我正在构建一个 Javascript 路由器并构建这样的路由:
route('/user/{name}', 'page', function() {
this.text = 'User: ' + this.name;
});
函数的作用域是当前路由,所以我可以在这里操作当前路由(this.text是view找的)
现在我的下一步是在路由中包含一个 XHR 请求,它类似于:
route('/user/{name}', 'page', function() {
this.text = 'Loading';
var request = new XMLHttpRequest();
request.open('GET', '/api/user', true);
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.responseText);
// here is the issue: 'this' now refers to
// the XHR request and not the scope of the router
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
})/* .bind(this); */ // keeping scope like this overwrites the XHR
request.send();
request = null;
});
这里的问题是我需要访问 XHR 范围 和 我的路由器范围。在 onreadystatechange 末尾使用 .bind 会覆盖 XHR 范围,而不设置它会覆盖路由器的范围。
那怎么办?有没有比 var that = this;
更干净的东西——肯定有办法吗?
怎么样:
route('/user/{name}', 'page', function() {
var routeScope = this;
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
console.log(this);
// "this" is xhr's scope, while
console.log(routeScope);
// routeScope is your router's scope
// ...
}
}
});
})
编辑:错误,只读了你的最后一句话......没关系。
最简单(也是非常清晰的方法)是像这样保持对路由范围的引用:
var that = this;
您还可以使用 .bind()
设置范围并直接从 reqest
变量访问请求属性。
对于您的示例(使用 bind
辅助函数,以支持旧浏览器):
var bind = function(fn, context) {
return function() {
fn.apply(context, arguments);
};
};
request.onreadystatechange = bind(function() {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
}, this);
所以我正在构建一个 Javascript 路由器并构建这样的路由:
route('/user/{name}', 'page', function() {
this.text = 'User: ' + this.name;
});
函数的作用域是当前路由,所以我可以在这里操作当前路由(this.text是view找的)
现在我的下一步是在路由中包含一个 XHR 请求,它类似于:
route('/user/{name}', 'page', function() {
this.text = 'Loading';
var request = new XMLHttpRequest();
request.open('GET', '/api/user', true);
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.responseText);
// here is the issue: 'this' now refers to
// the XHR request and not the scope of the router
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
})/* .bind(this); */ // keeping scope like this overwrites the XHR
request.send();
request = null;
});
这里的问题是我需要访问 XHR 范围 和 我的路由器范围。在 onreadystatechange 末尾使用 .bind 会覆盖 XHR 范围,而不设置它会覆盖路由器的范围。
那怎么办?有没有比 var that = this;
更干净的东西——肯定有办法吗?
怎么样:
route('/user/{name}', 'page', function() {
var routeScope = this;
request.onreadystatechange = (function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
console.log(this);
// "this" is xhr's scope, while
console.log(routeScope);
// routeScope is your router's scope
// ...
}
}
});
})
编辑:错误,只读了你的最后一句话......没关系。
最简单(也是非常清晰的方法)是像这样保持对路由范围的引用:
var that = this;
您还可以使用 .bind()
设置范围并直接从 reqest
变量访问请求属性。
对于您的示例(使用 bind
辅助函数,以支持旧浏览器):
var bind = function(fn, context) {
return function() {
fn.apply(context, arguments);
};
};
request.onreadystatechange = bind(function() {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
this.age = data.age;
this.gender = data.gender;
} else {
this.text = "Error";
}
}
}, this);