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