1.怎樣使用原生javascript發(fā)送異步請求
我們先新建一個model對象,里面保存著發(fā)送請求的類型、地址和要發(fā)送的數據。
然后實例化一個XMLHttpRequest對象和一個FormData分別用來發(fā)送數據和存放數據,在將model中存放的數據添加到FormData,最后通過XMLHttpRequest發(fā)送請求。
請求發(fā)送后只需要在XHR的onreadystatechange事件中監(jiān)聽請求的狀態(tài),當返回的readyState狀態(tài)為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中然后在后面處理成功或失敗的時候的操作。
如果中間需要變更參數再次發(fā)送請求就非常方便,而jquery中則是存放在一個對象中處理。
$http(model).success(function(data){}).error(function(data){});
那么我們怎么讓原生js在發(fā)送請求時也這樣方便呢?
在上面發(fā)送請求的例子中我們已經將參數分離到一個對象中存放了,剩下的只有讓處理函數返回自身然在調用就可以實現(xiàn)一樣的效果了。
我們在window下面新建$http函數然后下面還有一級ajax函數,而$http.ajax下面是不同狀態(tài)下的處理函數。
1.需要注意的是我們發(fā)送請求的時候回調是通過調用$http下面的success傳入一個函數來實現(xiàn)的,這種的話我們需要一個中間函數來存放我們傳入的回調函數,并保證在何時的時候執(zhí)行。
比如像下面這樣,調用函數success傳入success的回調用_success存放起來,如果你需要進度的話就加上progress,如果需要在發(fā)送前執(zhí)行的話也可以新建一個函數用來存放并在發(fā)送請求前調用。
$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時執(zhí)行了_success會拋出異常。
2.做好了回調函數的存放,接下來就是發(fā)請求了,這里我們監(jiān)聽了發(fā)送數據的進度progress,上傳文件的時候進度是很有必要的。
在進度監(jiān)聽中我們調用以存放好的_progress并把數據發(fā)送過去處理,在請求成功或失敗中調用存放好的_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(){});