Promise是什么占业?如何使用?
我們起點(diǎn)低一點(diǎn)纯赎,先從Promise說起吧谦疾。。我們先看Promise的調(diào)用
eg1:
let aPromise = new Promise(function(resolve, reject) {
console.log(233)
setTimeout(function(){
console.log(466)
resolve("DONE");
}, 250);
});
顯然犬金,Promise是個構(gòu)造函數(shù)(廢話)念恍,接受一個帶有resolve和reject兩個參數(shù)的函數(shù)作為參數(shù)。既然是構(gòu)造函數(shù)晚顷,肯定會想到原型(Prototype)方法和實例方法峰伙。Promise也確實有這些api,在介紹api之前该默,我覺得你應(yīng)該更關(guān)心Promise的使用瞳氓。
首先Promise接受的參數(shù)是立即執(zhí)行的。既在實例的化時栓袖,需要調(diào)用Promise的函數(shù)參數(shù)匣摘。如eg1,運(yùn)行該段代碼時裹刮,控制臺立即輸出233音榜,466隨后。是的必指,它就像是在你本來正常寫的異步操作外包了一層囊咏,并沒什么大的變化一樣,以往如果我們要有回調(diào)塔橡,則在466后編寫callback即可梅割。
Promise.then()
但是現(xiàn)在已經(jīng)不再如前了,請不要忽略 resolve("DONE");
此段代碼意味著成功回調(diào)時葛家,返回的值户辞。
我們在eg1后緊跟
aPromise.then(res=>{console.log(res)})
可以在控制臺看到466后緊跟著DONE,如果這是個獲取json的異步操作(并且我們調(diào)用resolve返回它)癞谒,此時我們拿到的可能就是json了底燎。
此時不免對.then
產(chǎn)生了興趣刃榨,.then是實例方法之一,接受兩個函數(shù)作為參數(shù)双仍,第二個參數(shù)是可選的枢希。
aPromise.then(onFulfilled[, onRejected]);
@題外話Q:這種寫法如何理解...
aPromise.then(function(value) {
// fulfillment
}, function(reason) {
// rejection
});
onFulfilled:
該函數(shù)提供一個參數(shù),是fulfilled狀態(tài)時的返回值朱沃,當(dāng)Promise狀態(tài)為fulfilled時苞轿,該函數(shù)被調(diào)用。
onRejected :
該函數(shù)提供一個參數(shù)逗物,是Rejected狀態(tài)時的返回值搬卒,當(dāng)Promise狀態(tài)為Rejected時,該函數(shù)被調(diào)用翎卓。
這里不免提一下實例的另一個方法契邀,.catch()
該方法只處理rejected狀態(tài)的返回值,調(diào)用形式同then失暴,其實你可以理解catch為
aPromise.then(undefined, onRejected);
promise.catch(function(rej) {
// 拒絕
console.log(rej)
});
Promise的狀態(tài)坯门?
是的我們又成功引出了一個新的東西,Promise的狀態(tài)锐帜,這里說的是實例的狀態(tài)田盈,也就是new返回的對象的狀態(tài)。
一個promise有三種狀態(tài):
pending:意味對象剛剛被創(chuàng)建缴阎,初始狀態(tài)
fulfilled:操作成功
rejected:操作失敗
那promise是如何從pengding向其他兩個狀態(tài)發(fā)展的呢允瞧?
回到最初的構(gòu)造函數(shù)。
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的狀態(tài)更為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只改變一次狀態(tài)
值得注意的是,無論是調(diào)用.then
還是調(diào)用.catch
二者都繼續(xù)(立即)返回一個promise對象建炫。如果你連續(xù)使用多個.then
畦韭,可以解釋為從.then()
回調(diào)中返回一個值,則會以該值調(diào)用下一個.then()
肛跌,若從.then()
回調(diào)中返回類promise的內(nèi)容艺配,下一個.then
則會等待promise的狀態(tài)變更settled(rejected/fulfilled)時調(diào)用。@Q:這塊其實并沒有完全懂...
這意味著我們可以這樣
getJson('a.json')
.then(json => {
return jsonOperate1(json)
})
.then(json2 => {
return jsonOperate2(json2)
})
.then(json3 => {
return jsonOperate3(json3)
})
拋棄原來的一層層遞進(jìn)的回調(diào)了...
但是衍慎,這里還需要注意一下.then與.catch的區(qū)別转唉。
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')
})
你能畫出如上代碼的流程圖嗎?(如果不能稳捆,也許你需要看看參考內(nèi)容...
同步發(fā)送請求的結(jié)果順序問題
試想這樣一個場景赠法,你先request一個pic.json,json是個數(shù)組乔夯,每一項有每張圖片的地址砖织,圖片是有順序的款侵,圖片需要依次按序展示。你會如何處理邏輯侧纯?一次性發(fā)起全部請求新锈,所有完成后順序展示?按順序發(fā)起圖片請求茂蚓,依次展示壕鹉?自然是一次性發(fā)起多個請求剃幌,順序列表之一的請求完成時聋涨,便開始展示...那具體又如何操作呢?
請看下篇...
參考內(nèi)容:
JavaScript Promise:簡介 | Web | Google Developers(推薦閱讀)
Promise - JavaScript | MDN
Promises/A+
JavaScript Promise迷你書