番外:深入理解Promise - 03 Promise的幾個重要問題
Promise的幾個重要問題
一、 Promise什麼時候發生狀態改變?什麼時候獲取值?
前面說過Promise的excutor是同步執行的回撥函式,但是可以觸發非同步任務,因此有兩種情況:
-
在excutor執行器中立即同步執行呼叫敲定函式,於是同步的例項改變狀態並且獲取到結果
-
在excutor執行器中非同步的執行呼叫敲定函式,比如setTimeout,於是非同步的改變例項狀態並獲取結果
二、Promise的例項什麼一定要改變狀態前指定回撥函式嗎?
不!Promise的例項可以在任何時候指定或者說繫結回撥函式
-
改變前:
const promise = new Promise((fulfill, reject) => { setTimeout(()=>{ fulfill(true) }, 1000) }) promise.then(onFulfilled, onRejected)
-
改變後:
同步的改變狀態const promise = new Promise((fulfill, reject) => { fulfill(true) }) promise.then(onFulfilled, onRejected)
或者,非同步的繫結回撥
const promise = new Promise((fulfill, reject) => { setTimeout(()=>{ fulfill(true) }, 1000) }) setTimeout(()=>{ promise.then(onFulfilled, onRejected) }, 2000)
三、 Promise的例項可以繫結多個then還是隻能繫結最後一個?
可以繫結多個,一旦promise例項的狀態發生轉變,按照繫結順序依次呼叫
const promise = new Promise((fulfill, reject) => {
setTimeout(()=>{
fulfill(true)
}, 1000)
})
promise.then(onFulfilled1, onRejected1)
promise.then(onFulfilled2, onRejected2)
最終 onFulfilled1 和 onFulfilled2 依次執行
四、 excutor 執行器 和 then 的回撥函式的關係
我們先整理一下,什麼操作能產生Promise例項
- new Prmoise(excutor)
- Prmoise.resolve
- Prmoise.reject
- Prmoise的例項呼叫then等方法
- promise.all、any等靜態方法 這個單獨考慮
我們對齊分類:
-
promise.all、any,對多個promise進行處理,併發或者競爭
-
使用 excutor ,能夠實現從0到有,即new Prmoise(excutor),Prmoise.resolve和Prmoise.reject只不過是對其的簡寫,特別是thenable物件的then幾乎和 excutor 一模一樣
-
then等方法,它顯得極為特殊,是在原有的promise新生成一個promise(注意原來的Promise例項每呼叫生成的新的Promise例項都是不同的)
但是如果你對then的結構、行為、效果仔細分析,它其實也是某種意義上的 excutor,我們假設一個場景:
const promise = new Promise((fulfill, reject) => {
setTimeout(()=>{
fulfill(true)
}, 1000)
})
promise.then(onFulfilled, onRejected)
根據promise.then的效果寫一些虛擬碼:
/*
當事件輪詢到執行Promise回撥時
if 當前的Promise例項狀態發生了改變 {
if(改變的狀態為 fulfilled) {
執行onFulfilled函式
}else if(改變的狀態為 rejected) {
執行onRejected函式
}
根據狀態處理函式結果返回 新的 Promise例項
}
*/
功能上,then的兩個處理函式 是對 excutor 的分解,onFulfilled的執行不僅僅是處理當前Promise例項的值,更是由其返回的值敲定新的Promise的狀態並儲存結果,onRejected也是如此。
對於返回的新的Promise例項其內部就像執行如下函式
- fullfill(onFulfilledResult)
- reject(onRejectedResult)
看下面這段程式碼
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(1)
console.log('內層promise')
}, 1000)
}))
console.log('外層promise')
}, 1000)
}).then((value)=>{
console.log(value)
})
這裡的resolve接受引數返回的新的Promise例項和then的onFulfilled呼叫返回值決定的新的Promise例項是一致的
五、串聯多個Promise任務
只要在excutor執行器上敲定函式的實參 或者 then的回撥函式返回值 指定的需要串聯的Promise例項,返回的新的Promise就會"跟隨"傳入該例項
六、異常穿透 => catch
let onFulfilled1 = function(value) {
console.log(value)
}
let onFulfilled2 = onFulfilled1
let onFulfilled3 = onFulfilled2
let onRejected = function(error) {
console.log(error, '錯誤獲取')
console.log(promise2 === promise1)
}
const promise = new Promise((fulfill, reject) => {
setTimeout(()=>{
reject(true)
}, 1000)
})
const promise1 = promise.then()
const promise2 = promise1.then()
promise2.then(onFulfilled3)
.catch(onRejected)
如果當前呼叫then方法的Promise例項已經發生狀態變化,並返回結果,但是找不到then傳入的處理對應的處理函式,並不會丟失,而是交給新返回的Promise例項使得新的例項的then能夠處理到上一個例項的結果。
或者說,如果then函式沒有傳入當前Promise例項對應狀態的處理函式,那麼預設返回一個和當前Promise例項狀態相同,結果相同的新的Promise
七、中斷Promise鏈
只要Promise的例項狀態不敲定,那麼then的回撥不會執行
let promise
promise = new Promise((fulfill, reject) => {
setTimeout(()=>{
reject(true)
}, 1000)
})
promise.then(
value => {
return new Promise((fulfill, reject) => {})//返回未敲定的Promise例項
},
errorReason => {
return new Promise((fulfill, reject) => {})//返回未敲定的Promise例項
}
)
//或者
promise = new Promise((fulfill, reject) => {
setTimeout(()=>{
reject(true)
}, 1000)
})
promise.finally(()=>{
return new Promise((fulfill, reject) => {})//返回未敲定的Promise例項
})
相關文章
- promise專題--手寫promise03Promise
- 深入理解Javascript之PromiseJavaScriptPromise
- es6-深入理解promisePromise
- 深入理解 ES6 PromisePromise
- 深入 PromisePromise
- 從手寫一個符合Promise/A+規範Promise來深入學習PromisePromise
- Promise深入探索Promise
- 深入理解Promise從這裡開始Promise
- promise的理解和使用Promise
- 深入理解 promise、generator+co、async/await 用法PromiseAI
- Promise重要知識點Promise
- 深入淺出PromisePromise
- Promise的祕密(Promise原理解析以及實現)Promise
- Promise使用時應注意的問題Promise
- Promise原理解讀Promise
- 簡單理解promisePromise
- Promise原理解析Promise
- Promise實用理解Promise
- 一個Promise面試題Promise面試題
- 非同步(一):Promise深入理解與例項分析非同步Promise
- 易理解的Promise封裝Promise封裝
- ES6 Promise理解Promise
- ES6 promise理解Promise
- Promise && async/await的理解和用法PromiseAI
- 談談你對Promise的理解Promise
- 關於 Promise 的 9 個面試題Promise面試題
- Promise和Promise的方法Promise
- Promise 原始碼:實現一個簡單的 PromisePromise原始碼
- 03、Promise,Vue-cli搭建專案PromiseVue
- Promise 的 9 個提示Promise
- JS每日一題: 如何理解es6中的Promise?JS每日一題Promise
- 深入理解javascript系列(十九):從Promise開始到async/awaitJavaScriptPromiseAI
- 實現一個完美符合Promise/A+規範的PromisePromise
- Promise原理講解 && 實現一個Promise物件 (遵循Promise/A+規範)Promise物件
- Promise, Generator, async/await的漸進理解PromiseAI
- ES6 Promise的使用和理解Promise
- Promise到底解決了什麼問題?Promise
- Promise面試題Promise面試題