JS中的promise
promise對(duì)象用于表示一個(gè)異步操作的最終完成 (或失敗),及其結(jié)果值。屬于ES6語(yǔ)法中的內(nèi)容。
用于處理異步問(wèn)題。
單線程是js的痛點(diǎn),因此,如何解決單線程問(wèn)題,引用了異步的概念,用異步來(lái)模擬多線程的用法。其中ajax是典型的利用異步加載數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)刷新的案例。
但在處理多個(gè)有相互依賴(lài)關(guān)系的異步操作時(shí),便會(huì)出現(xiàn)回調(diào)地獄。
//以ajax距離---回調(diào)地獄
ajax(function(){
ajax(function(){
ajax(function(){
ajax(function(){
})
})
})
})
極大的影響程序的運(yùn)行,占用內(nèi)存。
因此,promise提供了很好的解決方式,用于解決這些問(wèn)題。
promise對(duì)象是一個(gè)代理對(duì)象(代理一個(gè)值),被代理的值在promise對(duì)象創(chuàng)建時(shí)可能是未知的。它允許為異步操作的成功和失敗分別綁定相應(yīng)的處理方法,但不是立即返回執(zhí)行結(jié)果,而是返回成功或失敗的狀態(tài)。
語(yǔ)法new Promise( function(resolve, reject) {...}
promise有以下幾種狀態(tài):
- pending:初始狀態(tài),既不是成功,也不是失敗
- fulfilled:意味著操作成功
- rejected:意味著操作失敗
then()方法
在初始狀態(tài)時(shí),promise對(duì)象可能變成fulfilled狀態(tài)并返回一個(gè)相應(yīng)的狀態(tài)處理方法,也可能變成rejected狀態(tài)并返回一個(gè)失敗信息。當(dāng)其中一種情況出現(xiàn)時(shí),promise狀態(tài)便不會(huì)改變,而是成為其中的一種狀態(tài),promise的then方法綁定的處理方法handlers便會(huì)被調(diào)用。其中then方法中綁定了兩個(gè)參數(shù):onfulfilled 和 onrejected,當(dāng)返回的狀態(tài)是fulfilled,調(diào)用onfulfilled方法,當(dāng)返回的狀態(tài)是rejected,調(diào)用onrejected方法。
在promise的語(yǔ)法中,new Promise( function(resolve, reject) {...}當(dāng)promise被new創(chuàng)建時(shí),會(huì)有resolve, reject這兩個(gè)參數(shù)。其中當(dāng)異步任務(wù)成功并返回結(jié)果值是,會(huì)調(diào)用resolve函數(shù);而當(dāng)異步任務(wù)失敗并返回失敗原因時(shí),會(huì)調(diào)用reject函數(shù)。
以ajax為例:
function ajaxGet(url,data){
data = data || {};
var str = "";
for(var i in data){
str = str + i+"="+data[i]+"&";
}
var d = new Date();
url = url + "?" + str + "__htnt="+d.getTime();
var p = new Promise((resolve,reject)=>{
var xhr = new XMLHttpRequest();
xhr.open("get",url,true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
resolve(xhr.responseText);
}else if(xhr.readyState == 4 && xhr.status != 200){
reject(xhr.status)
}
}
xhr.send();
});
return p;
}
在這個(gè)ajax-get封裝中,當(dāng)傳輸成功時(shí),則將成功后得到數(shù)據(jù)返回作為參數(shù)返回給resolve函數(shù);當(dāng)失敗時(shí),將失敗狀態(tài)作為參數(shù)返回給reject函數(shù)。
假設(shè)此時(shí)它有返回值,且 var p = ajaxGet(...)
p.then(function(data){
console.log("成功");
console.log('返回值為:',data);
},function(data){
console.log("失敗");
console.log("錯(cuò)誤代碼:",data);
})
還可以在p.then(function(){})再加上.then(function(){}).then(function(){})
p.then(function(){
}).then(function(){
}).then(function(){
})...
可以將第一次異步得到的數(shù)據(jù)傳到第一個(gè)then中,然后在將從第一個(gè)then中處理的數(shù)據(jù)進(jìn)行第二次異步操作,并傳遞結(jié)果,依次往下傳遞。
catch()方法
添加一個(gè)拒絕(rejection)回調(diào)到當(dāng)前 promise, 返回一個(gè)新的promise。只用來(lái)捕獲失敗狀態(tài)。
finally()方法 --ES2018
finally添加一個(gè)事件處理回調(diào)與當(dāng)前promise對(duì)象,并且在原promise對(duì)象解析完畢后,返回一個(gè)新的promise對(duì)象。無(wú)論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行指定的回調(diào)函數(shù)。避免了同樣的語(yǔ)句需要在then()和catch()中各寫(xiě)一次的情況。
all()方法
假設(shè)情況如下:
var p1 = ajaxGet(...);
var p2 = ajaxGet(...);
var p3 = ajaxGet(...);
Promise.all([p1,p2,p3]).then(function(res){
console.log(res);
},function(res){
console.log(res);
})
all()的參數(shù)應(yīng)是一個(gè)數(shù)組。當(dāng)在這個(gè)數(shù)組中所有的promise對(duì)象都成功才會(huì)觸發(fā)成功,并把數(shù)組中所有promise返回值的數(shù)組作為成功回調(diào)的返回值,順序與數(shù)組中一致。若有任一個(gè)對(duì)象失敗。則會(huì)觸發(fā)該primise對(duì)象的失敗,并將第一個(gè)觸發(fā)失敗的promise對(duì)象的錯(cuò)誤信息作為它的失敗狀態(tài)。
race()方法
all()是等所有的異步操作都執(zhí)行完了再執(zhí)行then()方法,那么race()方法就是相反的,誰(shuí)先執(zhí)行完成就先執(zhí)行回調(diào)。
參考地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise