1.怎样使用原生javascript发送异步请求
我们先新建一个model对象,里面保存着发送请求的类型、地址和要发送的数据。
然后实例化一个XMLHttpRequest对象和一个FormData分别用来发送数据和存放数据,在将model中存放的数据添加到FormData,最后通过XMLHttpRequest发送请求。
请求发送后只需要在XHR的onreadystatechange事件中监听请求的状态,当返回的readyState状态为4时表示请求已完成,status返回200表示请求正常
var model={
type:'',
url:'',
data:{}
}
var xhr=new XMLHttpRequest();
var fd=new FormData();
xhr.onreadystatechange=function(e){
if(xhr.readyState==4){
if(xhr.status==200){
console.log(xhr.responseText);
}else{
console.log(xhr);
}
}
};
for(var item in model.data){
fd.append(item,model.data[item]);
}
xhr.open(model.type,model.url,true);
xhr.send(fd);
2.封装ajax请求使用更加方便
一直以来我都很喜欢angularjs的$http的ajax请求写法,写着感觉比JQuery的ajax更舒服。
就像下面这样,将参数放在model中然后在后面处理成功或失败的时候的操作。
如果中间需要变更参数再次发送请求就非常方便,而jquery中则是存放在一个对象中处理。
$http(model).success(function(data){}).error(function(data){});
那么我们怎么让原生js在发送请求时也这样方便呢?
在上面发送请求的例子中我们已经将参数分离到一个对象中存放了,剩下的只有让处理函数返回自身然在调用就可以实现一样的效果了。
我们在window下面新建$http函数然后下面还有一级ajax函数,而$http.ajax下面是不同状态下的处理函数。
1.需要注意的是我们发送请求的时候回调是通过调用$http下面的success传入一个函数来实现的,这种的话我们需要一个中间函数来存放我们传入的回调函数,并保证在何时的时候执行。
比如像下面这样,调用函数success传入success的回调用_success存放起来,如果你需要进度的话就加上progress,如果需要在发送前执行的话也可以新建一个函数用来存放并在发送请求前调用。
$http.ajax.prototype.success=function(fn){
this._success=fn;
return this;
};
$http.ajax.prototype._success=function(){};
$http.ajax.prototype.error=function(fn){
this._error=fn;
return this;
};
$http.ajax.prototype._error=function(){};
$http.ajax.prototype.progress=function(fn){
this._progress=fn;
return this;
};
$http.ajax.prototype._progress=function(){};
注意在success/error/progress中都返回了this这样你就可以在调用其中一个函数后接着调用同级的其他函数(上面因为new 了$http.ajax所以这是的this是指向一个$http.ajax的,而success/error/progress这三个函数都是放在这下面的),而_success之类的初始化的时候必须是function不然在未传入_success时执行了_success会抛出异常。
2.做好了回调函数的存放,接下来就是发请求了,这里我们监听了发送数据的进度progress,上传文件的时候进度是很有必要的。
在进度监听中我们调用以存放好的_progress并把数据发送过去处理,在请求成功或失败中调用存放好的_success/_error函数,做完这些后别忘了返回this,不然没办法调用下面的函数来存放处理函数。
$http.ajax=function(model){
var self=this;
var model=model;
var xhr=new XMLHttpRequest();
var fd=new FormData();
if(xhr.upload){
xhr.upload.addEventListener('progress',function(e){
self._progress(e);
});
xhr.onreadystatechange=function(e){
if(xhr.readyState==4){
if(xhr.status==200){
self._success(xhr.responseText);
}else{
self._error(xhr);
}
}
};
for(var item in model.data){
fd.append(item,model.data[item]);
}
xhr.open(model.type,model.url,true);
xhr.send(fd);
}
return this;
};
值得注意的是在这里返回this时_success/_error/_progress还没有存放我们传入的函数。
3.最后我们要让$http函数返回$http.ajax函数实例化对象,这样的话每一个请求相互之间就是相互隔离互不干扰的了。
window.$http=function(model){
return new $http.ajax(model);
};
使用的时候只需要像下面这样写就可以了,model配置以及数据、progress进度、success成功、error失败。
var model={
type:'',
url:'',
data:{}
}
$http(model).progress(function(data){}).success(function(data){}).error(function(){});