Promise,async/await,yield/generater(一)

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迷你書

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容