Promise是什么?如何使用?
我們起點低一點,先從Promise說起吧。。我們先看Promise的調用
eg1:
let aPromise = new Promise(function(resolve, reject) {
console.log(233)
setTimeout(function(){
console.log(466)
resolve("DONE");
}, 250);
});
顯然,Promise是個構造函數(廢話),接受一個帶有resolve和reject兩個參數的函數作為參數。既然是構造函數,肯定會想到原型(Prototype)方法和實例方法。Promise也確實有這些api,在介紹api之前,我覺得你應該更關心Promise的使用。
首先Promise接受的參數是立即執行的。既在實例的化時,需要調用Promise的函數參數。如eg1,運行該段代碼時,控制臺立即輸出233,466隨后。是的,它就像是在你本來正常寫的異步操作外包了一層,并沒什么大的變化一樣,以往如果我們要有回調,則在466后編寫callback即可。
Promise.then()
但是現在已經不再如前了,請不要忽略 resolve("DONE");
此段代碼意味著成功回調時,返回的值。
我們在eg1后緊跟
aPromise.then(res=>{console.log(res)})
可以在控制臺看到466后緊跟著DONE,如果這是個獲取json的異步操作(并且我們調用resolve返回它),此時我們拿到的可能就是json了。
此時不免對.then
產生了興趣,.then是實例方法之一,接受兩個函數作為參數,第二個參數是可選的。
aPromise.then(onFulfilled[, onRejected]);
@題外話Q:這種寫法如何理解...
aPromise.then(function(value) {
// fulfillment
}, function(reason) {
// rejection
});
onFulfilled:
該函數提供一個參數,是fulfilled狀態時的返回值,當Promise狀態為fulfilled時,該函數被調用。
onRejected :
該函數提供一個參數,是Rejected狀態時的返回值,當Promise狀態為Rejected時,該函數被調用。
這里不免提一下實例的另一個方法,.catch()
該方法只處理rejected狀態的返回值,調用形式同then,其實你可以理解catch為
aPromise.then(undefined, onRejected);
promise.catch(function(rej) {
// 拒絕
console.log(rej)
});
Promise的狀態?
是的我們又成功引出了一個新的東西,Promise的狀態,這里說的是實例的狀態,也就是new返回的對象的狀態。
一個promise有三種狀態:
pending:意味對象剛剛被創建,初始狀態
fulfilled:操作成功
rejected:操作失敗
那promise是如何從pengding向其他兩個狀態發展的呢?
回到最初的構造函數。
let aPromise = new Promise((resolve, reject) => {
setTimeout(function(){
console.log(466)
reject("REJECT");
}, 250);
});
aPromise.then((res)=>{console.log(res,'res')},rej =>{console.log(rej,"rej")})
此時控制臺輸出
466
REJECT rej
可以看出,可以通過resolve/reject將promise的狀態更為fulfilled/rejected。
let aPromise = new Promise((resolve, reject) => {
setTimeout(function () {
console.log(466);
reject("REJECT");
}, 250);
setTimeout(function () {
console.log(233);
resolve("DONE");
}, 600);
});
aPromise.then((res) => {
console.log(res, 'res')
}, rej => {
console.log(rej, "rej")
});
//輸出
466
REJECT rej
233
可以看到一個promise只改變一次狀態
值得注意的是,無論是調用.then
還是調用.catch
二者都繼續(立即)返回一個promise對象。如果你連續使用多個.then
,可以解釋為從.then()
回調中返回一個值,則會以該值調用下一個.then()
,若從.then()
回調中返回類promise的內容,下一個.then
則會等待promise的狀態變更settled(rejected/fulfilled)時調用。@Q:這塊其實并沒有完全懂...
這意味著我們可以這樣
getJson('a.json')
.then(json => {
return jsonOperate1(json)
})
.then(json2 => {
return jsonOperate2(json2)
})
.then(json3 => {
return jsonOperate3(json3)
})
拋棄原來的一層層遞進的回調了...
但是,這里還需要注意一下.then與.catch的區別。
getJson('a.json')
.then(json => {
return jsonOperate1(json)
})
.catch(err => {
return errOperate1(err)
})
.then(json2 => {
return jsonOperate2(json2)
})
.then(json3 => {
return jsonOperate3(json3)
})
.catch(err => {
return errOperate(err)
})
.then(() => {
console.log('END')
})
你能畫出如上代碼的流程圖嗎?(如果不能,也許你需要看看參考內容...
同步發送請求的結果順序問題
試想這樣一個場景,你先request一個pic.json,json是個數組,每一項有每張圖片的地址,圖片是有順序的,圖片需要依次按序展示。你會如何處理邏輯?一次性發起全部請求,所有完成后順序展示?按順序發起圖片請求,依次展示?自然是一次性發起多個請求,順序列表之一的請求完成時,便開始展示...那具體又如何操作呢?
請看下篇...
參考內容:
JavaScript Promise:簡介 | Web | Google Developers(推薦閱讀)
Promise - JavaScript | MDN
Promises/A+
JavaScript Promise迷你書