前言
繼續之前 ES6 - Promise(1),繼續來研究 Promise,今天要來研究的是 Promise 的 then 方法。
語法
then 方法回傳一個 Promise。它接收兩個參數: Promise 在成功及失敗情況時的回呼函式。1
2
3
4
5
6
7p.then(onFulfilled[, onRejected]);
p.then(function(value) {
// fulfillment
}, function(reason) {
// rejection
});
參數
- onFulfilled
一個函式,當 Promise 被實現(fulfilled)時被呼叫。此函式接收一個 fullfillment value 作為參數。 - onRejected (optional)
一個函式,當 Promise 被拒絕(rejected)時被呼叫。此函式接收一個 rejection reason 作為參數。
回傳值
當 Promise 在 pending 的狀態的時候。then 的 handler function (onFulfilled 或 onRejected)會非同步地被呼叫,
MDN 上關於被調用後,handler function 回傳的值有五種情況,詳細的敘述可以參考 MDN,這裡不多作解釋,直接看範例會比較容易理解。
1 | var resolvedProm = Promise.resolve(33); |
其他
then()和catch()方法都會回傳 Promise,所以可以串接在一起。
範例
then() 的使用
1 | var p1 = new Promise( (resolve, reject) => { |
then() 的串接
使用 setTimeout 來模擬非同步的效果。
1 | Promise.resolve('foo') |
依序回傳的順序是:1
2
3
4
5"before return Promise"
"before setTimeout"
"Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising"
"lastfoobar"
"foobarbaz"
一開始的 Promise.resolve() 靜態設定 Promise 已經是實現的狀態,會直接回傳 resolve 的值。並執行第一個 then(),所以先印出 “before return Promise”,接著回傳一個新的 Promise,這裡因為設計了一個 setTimeout 所以會有時間間隔,當它還在等待並執行 new Promise 的 statement 的時候,javascript 會先繼續向下執行下一個 then(),印出 “before setTimeout”。但是該 then() 的 handler 又有一個 setTimeout 函示在等著執行,所以接著進入最後一個 then(),印出那一長串文字。在這同時第一個 then() 回傳的 promise 已經執行完畢並 resolve string = lastfoobar,所以會接著印出 “lastfoobar”。最後才會印出 “foobarbaz”。
為什麼最後一個 then() 印出的文字沒有 “baz” ? 這是因為透過 setTimeout 還模擬非同步的情況,第一個 then() 回傳 string 的時候,當第二個 then() 還沒有執行完的時候就先傳到了第三個 then(),所以第三個 then() 回傳的文字不帶會有第二個 then() 回傳的值。
如果我們把 setTimeout 函示拿掉,回傳的順序會變成1
2
3
4
5"before return Promise"
"before setTimeout"
"foobarbaz"
"Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising"
"lastfoobarbaz"
兩種結果互相比較,就可以更加了解 then() 在非同步情況下的執行方式。
使用 then() 回傳一個 reject 的 promise
因為 then() 回傳一個 reject 的 promise,所以會執行 onRejected 函示。
最後回傳 “onRejected function called: Oh no!”1
2
3
4
5
6
7
8
9Promise.resolve()
.then( () => {
throw 'Oh no!';
})
.then( () => {
console.log( 'Not called.' );
}, reason => {
console.error( 'onRejected function called: ', reason );
});
reject() 的情況
1 | Promise.reject() |
reject 的時候,會執行 onRejected 函示,也就是會回傳 42。
實務上的用法
實務上,推薦盡量使用 catch 去處理 promise reject 的情況,不建議使用兩個參數 then() 語法。
1 | Promise.resolve() |