Javascript 如何在XHR请求中保持作用域?
因此,我正在构建一个Javascript路由器,并构建一条如下所示的路由:Javascript 如何在XHR请求中保持作用域?,javascript,scope,xmlhttprequest,url-routing,Javascript,Scope,Xmlhttprequest,Url Routing,因此,我正在构建一个Javascript路由器,并构建一条如下所示的路由: route('/user/{name}', 'page', function() { this.text = 'User: ' + this.name; }); var that = this; 函数的作用域是当前路由,因此我可以在这里操作当前路由(this.text是视图所要查找的) 现在,我的下一步是在路由中包含一个XHR请求,它看起来像: route('/user/{name}', 'page', fu
route('/user/{name}', 'page', function() {
this.text = 'User: ' + this.name;
});
var that = this;
函数的作用域是当前路由,因此我可以在这里操作当前路由(this.text是视图所要查找的)
现在,我的下一步是在路由中包含一个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;
});
route('/user/{name}',page',function(){
this.text='Loading';
var request=new XMLHttpRequest();
open('GET','/api/user',true);
request.onreadystatechange=(函数(){
if(this.readyState==4){
如果(this.status>=200&&this.status<400){
var data=JSON.parse(this.responseText);
//问题是:“这个”现在指的是
//XHR请求,而不是路由器的作用域
this.age=data.age;
this.gender=data.gender;
}否则{
this.text=“Error”;
}
}
})/*.bind(this);*///这样保留作用域会覆盖XHR
request.send();
请求=null;
});
这里的问题是我需要访问XHR范围和我的路由器范围。在onreadystatechange的末尾使用.bind会覆盖XHR范围,而不设置它会覆盖路由器的范围
那你怎么办?是否有比var=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
// ...
}
}
});
})
route('/user/{name}',page',function(){
var routeScope=this;
request.onreadystatechange=(函数(){
if(this.readyState==4){
如果(this.status>=200&&this.status<400){
console.log(this);
//“这”是xhr的范围,而
控制台日志(routeScope);
//routeScope是路由器的作用域
// ...
}
}
});
})
编辑:嗯,读一下你的最后一句话。。。无需担心。最简单(也是非常清楚的方法)是将对route范围的引用保持如下:
route('/user/{name}', 'page', function() {
this.text = 'User: ' + this.name;
});
var that = this;
您还可以使用.bind()
设置范围,并直接从reqest
变量访问请求属性
对于您的示例(使用bind
helper函数,以支持旧浏览器):
var bind=function(fn,上下文){
返回函数(){
fn.应用(上下文、参数);
};
};
request.onreadystatechange=bind(函数(){
if(request.readyState==4){
如果(request.status>=200&&request.status<400){
var data=JSON.parse(request.responseText);
this.age=data.age;
this.gender=data.gender;
}否则{
this.text=“Error”;
}
}
},这个);
this
不能从this.age
和this.gender
中删除this
?为什么不:var that=this代码>?这可能不是最优雅的方式,但它是有效的…这只是我的问题,有没有更干净的方式来保持范围。Buuut我想没有办法避免它,因为'this'将与'this'一起分类,也许解决方案是设置默认范围变量的一种方法。谢谢@ChrisL和maze le@ChrisL不,它会报告“年龄”/“性别”没有定义。控制器函数的调用方式如下:route.controller.apply(数据)代码>谢谢,我想最干净的方法就是更改scope变量。。我真的很喜欢你的例子(就我个人而言,我更喜欢保持作用域和变量名的一致性,这就是为什么我走这条路线),但它真的只在Chrome中受支持?哦,对不起。。。我把ES5bind
与Object混淆了。请注意ES7提案中的绑定。这只是一个快速浏览,感谢您确认:P我想您可能指的是fn.apply(内容、参数)
行,因为我的mdn到处竖起大拇指:()。是的,我可以做到,而且可能会做到。主要是跨范围的一致性。谢谢你。