為什麼要使用Promise,Promise的優點
阿新 • • 發佈:2021-11-19
1.指定回撥函式的方式更加靈活:
舊的: 必須在啟動非同步任務前指定 promise: 啟動非同步任務 => 返回promie物件 => 給promise物件繫結回撥函式(甚至可以在非同步任務結束後指定) `
假設現在有一個名為 createAudioFileAsync() 的函式,如果給出一些配置和兩個回撥函式,這個函式能非同步地生成音訊檔案。一個回撥函式是檔案成功建立時的回撥,另一個則是出現異常時的回撥。
- 不使用Promise,回撥函式必須先指定
// 成功的回撥函式 function successCallback (result) { console.log('聲音檔案建立成功: ' + result) } // 失敗的回撥函式 function failureCallback (error) { console.log('聲音檔案建立失敗: ' + error) } /* 1.1 使用純回撥函式 */ createAudioFileAsync(audioSettings, successCallback, failureCallback)
- 使用Promise
const promise = createAudioFileAsync(audioSettings)
promise.then(successCallback, failureCallback)
// 可簡寫為
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
可以在非同步操作完成後再指定回撥函式
setTimeout(() => {
promise.then(successCallback, failureCallback)
}, 3000)
2.支援鏈式呼叫(將非同步操作以同步操作的流程表達出來), 可以解決回撥地獄問題
什麼是回撥地獄? 回撥函式巢狀呼叫, 外部回撥函式非同步執行的結果是巢狀的回撥函式執行的條件
回撥地獄的缺點? 不便於閱讀 / 不便於異常處理
解決方案? promise鏈式呼叫
終極解決方案? async/await
- 回撥地獄
doSomething(function (result) {
doSomethingElse(result, function (newResult) {
doThirdThing(newResult, function (finalResult) {
console.log('Got the final result: ' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
- 使用promise的鏈式呼叫解決回撥地獄
doSomething().then(function (result) {
return doSomethingElse(result)
})
.then(function (newResult) {
return doThirdThing(newResult)
})
.then(function (finalResult) {
console.log('Got the final result: ' + finalResult)
})
.catch(failureCallback)
======
// 箭頭函式寫法
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log(`Got the final result: ${finalResult}`)
})
.catch(failureCallback)
- async/await: 回撥地獄的終極解決方案
async function request () {
try {
const result = await doSomething()
const newResult = await doSomethingElse(result)
const finalResult = await doThirdThing(newResult)
console.log('Got the final result: ' + finalResult)
} catch (error) {
failureCallback(error)
}
}
Promise的缺點:
- 無法取消Promise,一旦新建它就會立即執行,無法中途取消。
- 如果不設定回撥函式,Promise內部丟擲的錯誤,不會反應到外部。
- 當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// 下面一行會報錯,因為x沒有宣告
resolve(x + 2);
});
};
someAsyncThing().then(function() {
console.log('everything is great');
});
setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123
上面程式碼中,someAsyncThing函式產生的 Promise 物件,內部有語法錯誤。瀏覽器執行到這一行,會打印出錯誤提示ReferenceError: x is not defined,但是不會退出程序、終止指令碼執行,2 秒之後還是會輸出123。這就是說,Promise 內部的錯誤不會影響到 Promise 外部的程式碼,通俗的說法就是“Promise 會吃掉錯誤”。