1- Promise的三種狀態:
1- Pending(等待,未完成,進行中)
2- Resolved(成功)
3- Rejected(失敗)
2- Promise的三種狀態關係變化只有兩種:
1- Pending => Resolved(從 ‘等待’ 變成 ‘成功’ )
2- Pending => Rejected( 從 ‘等待’ 變成 ‘失敗’ )
3- 狀態一旦改變,無法再次改變
3- Promise可以用來解決:
1- 解決多次併發請求:通過Promise.all來獲取’所有 併發請求 都成功’ 後的數據集合
2- 解決回調地獄:通過.then,.catch,.all,.race解決 異步請求success回調裏繼續執行函數或者異步請求造成的層層嵌套,造成的可讀性差,難維護
4- Promise的resolved和rejected 以及 then和catch:先上代碼
function demo(){
return new Promise((resolve,reject)=>{
$.ajax({
url: "http://api.local.com/?type=list",
method: "get",
header: {'content-type': 'application/json'},
success: res=>{
// 此處執行resolve(res),才能通過.then來調用,並且.then裏接收到的值就是這裏傳進去的
resolve(res)
},
error: err=>{
reject(err)
}
});
});
};
// 執行,查看結果
demo().then(data=>{
console.log( data , "成功")
}, err=>{
console.log( err , "失敗" )
});
// 第二種寫法,通過catch來捕獲reject錯誤失敗狀態
demo().then(data=>{
console.log( data , "成功")
}).catch(err=>{
console.log( err , "失敗catch" )
});
- then返回一個新的Promise,裏面接收兩個參數,第一個參數(必選)爲resolve成功回調,第二個參數(可選)爲reject失敗回調
- catch是當promise拋出錯誤變時被調用,等同於then裏的第二個err參數
- success或者error的回調裏調用 resolve(res) 或者reject(err) 方法,並傳入返回參數。如果不執行對應函數,無法通過then來鏈式調用。執行但是不傳入參數,then裏則無法獲取返回參數。可自行敲代碼看下打印輸出
5- Promise,解決回調地獄,多層嵌套:
// 分成三個方法,每個方法單獨處理,只做自己的事情
// 1- 詢問帥不帥
function handSome(){
console.log('開始詢問帥不帥')
return new Promise((resolve,reject)=>{
$.ajax({
url: "http://api.local.com/?type=list",
success: res=>{
console.log('很帥');
resolve(res);
},
error: err=>{
console.log('不帥');
reject(err)
}
});
});
};
// 2- 根據handSome回答,自己照鏡子確認
function confirm(data){
console.log('開始照鏡子:', data)
return new Promise( (resolve,reject)=>{
$.ajax({
url: "http://api.local.com/?type=list",
success: res=>{
console.log('照鏡子後確認很帥')
resolve(res)
},
error: err=>{
console.log('照鏡子後確認不帥')
reject(err)
}
});
});
};
// 3- confirm確認後,心情變化
function determine(data){
console.log('心情開始變化:',data)
return new Promise( (resolve,reject)=>{
$.ajax({
url: "http://api.local.com/?type=list",
success: res=>{
console.log('很開心')
resolve(res)
},
error: err=>{
console.log('不開心')
reject(err)
}
});
});
};
- 先來第一種調用:只調用成功回調
handSome().then(confirm).then(determine)
// 開始詢問帥不帥
// 很帥
// 開始照鏡子: (2) [{…}, {…}]
// 照鏡子後確認很帥
// 心情開始變化: (2) [{…}, {…}]
// 很開心
handSome().then(confirm).then()
// 開始詢問帥不帥
// 很帥
// 開始照鏡子: (2) [{…}, {…}]
// 照鏡子後確認很帥
- 上面寫法比較簡潔,等同於下面寫法
handSome().then(res=>{
confirm(res)
}).then(res=>{
determine(res);
});
- 來個帶有報錯的完整寫法(假設所有接口都失敗)
handSome().then(confirm, err=>{
console.log("handSome說我不帥")
}).then( determine, err=>{
console.log("照鏡子後確實不帥")
}).then(res=>{},err=>{
console.log("心情最後不開心")
});
// 開始詢問帥不帥
// 不帥
// handSome說我不帥
// 心情開始變化: undefined
// 不開心
// 心情最後不開心
根據上面調用的結果可總結出:
- 如果promise執行成功,並且還有then() 調用,則執行then() 中的第一個res參數
- 如果promise執行失敗,並且還有then() 調用,則執行then() 中的第二個err參數
- 有個特殊點,當err參數執行完畢後,後面還有then() 調用,則從then() 中的第一個參數開始,而不是繼續第二個參數調用
- 直到找不到then() ,開始狀態改變爲resolve或者rejected。
6- Promise的all和race
- Promise.all可以將多個Promise封裝成一個Promise。
- 並且,只有都請求成功的時候,纔會執行第一個參數,並且把多個請求結果封裝成數組返回
- 有執行失敗的,則返回最先被reject失敗狀態的值。
- 適合用在前端多個請求的情景
Promise.all([handSome(),confirm()]).then(res=>{
console.log( "兩個接口都確認了,我很帥" )
console.log( '兩個接口數據爲:',res)
},err=>{
console.log( "兩個接口,有失敗的" )
console.log( "失敗接口:",err)
});
都請求成功的打印輸出
有請求失敗的打印輸出
- Promise.race,哪個結果獲得的快,就返回那個結果,不管結果本身是成功狀態還是失敗狀態。
Promise.race([handSome(),confirm()]).then(res=>{
console.log( '有先好的' )
console.log( res )
})
打印結果
注:原先寫confirm方法,是用在handSome回調之後,可以獲取handSome返回的參數。在Promise.all和Promise.race中調用時,同步執行,所以confirm方法打印的data會undefined
如有錯誤,請大牛指出,及時修改