關(guān)于 JavaScript 中的 Promise,你應(yīng)該知道的五件事
Promise 模式是現(xiàn)代 JavaScript 編程的必備條件。 使用 then/catch 鏈接看起來很簡單,但它有一些我們最好知道的細(xì)節(jié)。 這篇文章將帶來關(guān)于 Promise 的 5 件事。
1. 反復(fù)解決
如果下面的代碼運(yùn)行會發(fā)生什么?
new Promise(resolve => {
resolve(new Promise(resolve => {
resolve(new Promise(resolve => {
resolve(10)
}))
}))
})
.then(value => console.log(value)) // 10
then() 給你 10(不是 Promise 實(shí)例)。 如果解析的值是一個 Promise,那么它會解析直到它不能 then-able。
2.返回鏈
then() 鏈不僅是函數(shù)鏈,還是價值鏈。
Promise.resolve(10)
.then(value => value + 1)
.then(value => value + 1)
.then(value => console.log(value)) // 12
第一個 then() 為該值提供 10,第二個為 11,第三個為 12。它還對返回的值應(yīng)用循環(huán)鏈,因此以下代碼的工作方式相同。
Promise.resolve(10)
.then(value => value + 1)
.then(value => Promise.resolve(value + 1))
.then(value => console.log(value)) // 12
3.then()的第二個參數(shù)
then() 實(shí)際上有 2 個參數(shù)。 第二個參數(shù)采用一個函數(shù)來處理拒絕的情況。 它與 catch() 的工作方式非常相似。 以下代碼的結(jié)果是相同的。
/// then() with second parameter
Promise.reject(10)
.then(
value => value + 1,
reason => handleError(reason), // reason=10
)/// then() and catch()
Promise.reject(10)
.then(value => value + 1)
.catch(reason => handleError(reason)) // reason=10
如果我們兩個都像下面這樣呢?
Promise.reject(10)
.then(
value => value + 1,
reason => handleError1(reason), // called
)
.catch(reason => handleError2(reason)) // not called
如果兩者都給出,則 then() 的第二個參數(shù)在 catch() 之前,因此調(diào)用了 handleError1() 而不會調(diào)用 handleError2()。 唯一的例外是 Promise 實(shí)際拋出錯誤的情況。 請參閱下面的代碼。
new Promise(() => { throw 'error' })
.then(
value => value + 1,
reason => handleError1(reason), // not called
)
.catch(reason => handleError2(reason)) // called
它僅在 catch() 子句中捕獲錯誤,因此調(diào)用了 handleError2()。 一個有趣的部分是,如果它沒有 catch(),即使使用 onReject 參數(shù)也會拋出錯誤。
4. then() 中拋出錯誤
如果 then() 中發(fā)生錯誤,它會在 catch() 子句中捕獲。
Promise.resolve(10)
.then(value => { throw 'error' })
.catch(reason => handleError(reason)) // catch!
5.錯誤作為一個值
如果我們嘗試用錯誤來解決,這聽起來很有趣。 你能想象下面的代碼會發(fā)生什么嗎?
Promise.resolve(new Error('error'))
.then(value => console.log(value)) // Error value
.catch(reason => handleError(reason))
它不會捕獲但會正常解析,因此它會記錄原始錯誤。 Promise 不賦予 Error 權(quán)限,而是 Promise 本身。
..和一個建議
Promise 模式對于處理異步作業(yè)很有用,但它通常涉及帶有嵌套 Promise 的曲線代碼。 它不利于閱讀,因此另一種選擇是使用 async/await。 現(xiàn)代 JavaScript 打包器提供了 async/await 語法的轉(zhuǎn)換。