什麼是Promise?
Promise 是異步編程的一種解決方案:從語法上講,promise是一個對象,從它可以獲取異步操作的消息;從本意上講,它是承諾,承諾它過一段時間會給你一個結果。promise有三種狀態:pending(等待態),fulfiled(成功態),rejected(失敗態);狀態一旦改變,就不會再變。創造promise實例後,它會立即執行。
我們用Promise來解決什麼問題?
promise是用來解決兩個問題的:
- 回調地獄,代碼難以維護, 常常第一個的函數的輸出是第二個函數的輸入這種現象
- promise可以支持多個併發的請求,獲取併發請求中的數據
- 這個promise可以解決異步的問題,本身不能說promise是異步的
相關資料:
https://juejin.im/post/5e650f646fb9a07cb83e3209
https://juejin.im/post/5a9516885188257a6b061d72
https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544
https://blog.csdn.net/weixin_41817034/article/details/80492315
面試題:
https://www.jianshu.com/p/84ef1b48fcce
常見 Promise 面試題
我們看一些 Promise 的常見面試問法,由淺至深。
- 1、瞭解 Promise 嗎?
- 2、Promise 解決的痛點是什麼?
- 3、Promise 解決的痛點還有其他方法可以解決嗎?如果有,請列舉。
- 4、Promise 如何使用?
- 5、Promise 常用的方法有哪些?它們的作用是什麼?
- 6、Promise 在事件循環中的執行過程是怎樣的?
- 7、Promise 的業界實現都有哪些?
- 8、能不能手寫一個 Promise 的 polyfill。
這些問題,如果你都能 hold 住,那麼面試官基本認可你了。帶着上面這些問題,我們往下看。
Promise 出現的原因
在 Promise 出現以前,我們處理一個異步網絡請求,大概是這樣:
// 請求 代表 一個異步網絡調用。
// 請求結果 代表網絡請求的響應。
請求1(function(請求結果1){
處理請求結果1
})
看起來還不錯。
但是,需求變化了,我們需要根據第一個網絡請求的結果,再去執行第二個網絡請求,代碼大概如下:
請求1(function(請求結果1){
請求2(function(請求結果2){
處理請求結果2
})
})
看起來也不復雜。
但是需求是永無止境的,於是乎出現瞭如下的代碼:
請求1(function(請求結果1){
請求2(function(請求結果2){
請求3(function(請求結果3){
請求4(function(請求結果4){
請求5(function(請求結果5){
請求6(function(請求結果3){
...
})
})
})
})
})
})
這回傻眼了。。。 臭名昭著的 回調地獄 現身了。
更糟糕的是,我們基本上還要對每次請求的結果進行一些處理,代碼會更加臃腫,在一個團隊中,代碼 review 以及後續的維護將會是一個很痛苦的過程。
回調地獄帶來的負面作用有以下幾點:
- 代碼臃腫。
- 可讀性差。
- 耦合度過高,可維護性差。
- 代碼複用性差。
- 容易滋生 bug。
- 只能在回調裏處理異常。
出現了問題,自然就會有人去想辦法。這時,就有人思考了,能不能用一種更加友好的代碼組織方式,解決異步嵌套的問題。
let 請求結果1 = 請求1();
let 請求結果2 = 請求2(請求結果1);
let 請求結果3 = 請求3(請求結果2);
let 請求結果4 = 請求2(請求結果3);
let 請求結果5 = 請求3(請求結果4);
類似上面這種同步的寫法。 於是 Promise 規範誕生了,並且在業界有了很多實現來解決回調地獄的痛點。比如業界著名的 Q 和 bluebird,bluebird 甚至號稱運行最快的類庫。
看官們看到這裏,對於上面的問題 2 和問題 7 ,心中是否有了答案呢。
什麼是 Promise
Promise 是異步編程的一種解決方案,比傳統的異步解決方案【回調函數】和【事件】更合理、更強大。現已被 ES6 納入進規範中。
代碼書寫比較
還是使用上面的網絡請求例子,我們看下 Promise 的常規寫法:
new Promise(請求1)
.then(請求2(請求結果1))
.then(請求3(請求結果2))
.then(請求4(請求結果3))
.then(請求5(請求結果4))
.catch(處理異常(異常信息))
比較一下這種寫法和上面的回調式的寫法。我們不難發現,Promise 的寫法更爲直觀,並且能夠在外層捕獲異步函數的異常信息。