本文大部分內(nèi)容是阮一峰老師的文章,這里搬過來也是為了自己記錄,想看更加詳細(xì)的教程請移步阮一峰老師個人博客
1.Promise.prototype.then()
then
方法返回的是一個新的Promise
實例(注意,不是原來那個Promise
實例)。因此可以采用鏈?zhǔn)綄懛ǎ?code>then()方法后面再調(diào)用另一個 then()
方法瑞躺。
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
采用鏈?zhǔn)降? then
,可以指定一組按照次序調(diào)用的回調(diào)函數(shù)屡拨。這時丈攒,前一個回調(diào)函數(shù),有可能返回的還是一個Promise
對象(即有異步操作)渣淳,這時后一個回調(diào)函數(shù)脾还,就會等待該Promise
對象的狀態(tài)發(fā)生變化伴箩,才會被調(diào)用入愧。
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log("resolved: ", comments);
}, function funcB(err){
console.log("rejected: ", err);
});
上面代碼中,第一個then方法指定的回調(diào)函數(shù)嗤谚,返回的是另一個Promise
對象棺蛛。這時,第二個then()
方法指定的回調(diào)函數(shù)巩步,就會等待這個新的Promise
對象狀態(tài)發(fā)生變化旁赊。如果變?yōu)?code>resolved,就調(diào)用funcA
椅野,如果狀態(tài)變?yōu)?code>rejected终畅,就調(diào)用funcB
籍胯。
上面代碼對應(yīng)的更簡潔的箭頭函數(shù)寫法為:
getJSON("/post/1.json").then(
post => getJSON(post.commentURL)
).then(
comments => console.log("resolved: ", comments),
err => console.log("rejected: ", err)
);
看下面一個使用的綜合案例
let pro = new Promise(function(resolve,reject){
if(true){
//調(diào)用操作成功方法
resolve('操作成功');
}else{
//調(diào)用操作異常方法
reject('操作異常');
}
});
//用then處理操作成功,catch處理操作異常
pro.then(requestA)
.then(requestB)
.then(requestC)
.catch(requestError);
function requestA(){
console.log('請求A成功');
return '請求B离福,下一個就是你了';
}
function requestB(res){
console.log('上一步的結(jié)果:'+res);
console.log('請求B成功');
return '請求C杖狼,下一個就是你了';
}
function requestC(res){
console.log('上一步的結(jié)果:'+res);
console.log('請求C成功');
}
function requestError(){
console.log('請求失敗');
}
//打印結(jié)果:
//請求A成功
//上一步的結(jié)果:請求B,下一個就是你了
//請求B成功
//上一步的結(jié)果:請求C妖爷,下一個就是你了
//請求C成功
案例中蝶涩,先是創(chuàng)建一個實例,還聲明了4個函數(shù)絮识,其中三個是分別代表著請求A绿聘,請求B,請求C次舌;有了then方法熄攘,三個請求操作再也不用層層嵌套了。我們使用then方法彼念,按照調(diào)用順序鲜屏,很直觀地完成了三個操作的綁定,并且国拇,如果請求B依賴于請求A的結(jié)果洛史,那么,可以在請求A的程序用使用return語句把需要的數(shù)據(jù)作為參數(shù)酱吝,傳遞給下一個請求也殖,案例中我們就是使用return實現(xiàn)傳遞參數(shù)給下一步操作的。
Promise.all( )方法
Promise.all( )
方法:接受一個數(shù)組作為參數(shù)务热,數(shù)組的元素是Promise
實例對象忆嗜,當(dāng)參數(shù)中的實例對象的狀態(tài)都為fulfilled
時,Promise.all( )
才會有返回崎岂。
//創(chuàng)建實例pro1
let pro1 = new Promise(function(resolve){
setTimeout(function () {
resolve('實例1操作成功');
},5000);
});
//創(chuàng)建實例pro2
let pro2 = new Promise(function(resolve){
setTimeout(function () {
resolve('實例2操作成功');
},1000);
});
Promise.all([pro1,pro2]).then(function(result){
console.log(result);
});
//打印結(jié)果:["實例1操作成功", "實例2操作成功"]
上述案例捆毫,我們創(chuàng)建了兩個Promise實例:pro1和pro2,我們注意兩個setTimeout的第二個參數(shù)冲甘,分別是5000毫秒和1000毫秒绩卤,當(dāng)我們調(diào)用Promise.all( )方法的時候,會延遲到5秒才控制臺會輸出結(jié)果江醇。
因為1000毫秒以后濒憋,實例pro2進入了成功fulfilled狀態(tài);此時陶夜,Promise.all( )還不會有所行動凛驮,因為實例pro1還沒有進入成功fulfilled狀態(tài);等到了5000毫秒以后条辟,實例pro1也進入了成功fulfilled狀態(tài)黔夭,Promise.all( )才會進入then方法宏胯,然后在控制臺輸出:["實例1操作成功","實例2操作成功"]。
這個方法有什么用呢本姥?一般這樣的場景:我們執(zhí)行某個操作胳嘲,這個操作需要得到需要多個接口請求回來的數(shù)據(jù)來支持,但是這些接口請求之前互不依賴扣草,不需要層層嵌套了牛。這種情況下就適合使用Promise.all( )方法,因為它會得到所有接口都請求成功了辰妙,才會進行操作鹰祸。
Promise.race( )方法
另一個類似的方法是Promise.race()方法:它的參數(shù)要求跟Promise.all( )方法一樣,不同的是密浑,它參數(shù)中的promise實例蛙婴,只要有一個狀態(tài)發(fā)生變化(不管是成功fulfilled還是異常rejected),它就會有返回尔破,其他實例中再發(fā)生變化街图,它也不管了。
//初始化實例pro1
let pro1 = new Promise(function(resolve){
setTimeout(function () {
resolve('實例1操作成功');
},4000);
});
//初始化實例pro2
let pro2 = new Promise(function(resolve,reject){
setTimeout(function () {
reject('實例2操作失敗');
},2000);
});
Promise.race([pro2,pro1]).then(function(result){
console.log(result);
}).catch(function(error){
console.log(error);
});
//打印結(jié)果:實例2操作失敗
同樣是兩個實例懒构,實例pro1不變餐济,不同的是實例pro2,這次我們調(diào)用的是失敗函數(shù)reject胆剧。
由于pro2實例中2000毫秒之后就執(zhí)行reject方法絮姆,早于實例pro1的4000毫秒,所以最后輸出的是:實例2操作失敗秩霍。
以上就是對Promise對象的內(nèi)容講解篙悯,上面提到了一個概念:回調(diào)地獄;指的是過多地使用回調(diào)函數(shù)嵌套铃绒,使得調(diào)試和維護起來極其的不便鸽照。
參考:微信文章教你如何使用ES6的Promise對象
https://segmentfault.com/a/1190000002928371
http://www.cnblogs.com/tugenhua0707/p/7337022.html