核心
其實 await 本質上等的是:後面的 thenable 對象的 then 方法調用 resolve 或者 reject。
這裏面其實包含三個細節:
- thenable 對象其實就是包含 then 方法的普通對象。
- 如果 await 後面的對象不是一個 thenable 對象,那麼系統會將它包裝成 thenable 對象。
- Promise 對象具有 then 方法,所以 Promise 對象其實也是一個 thenable 對象。
如果理解了這三個細節,那麼下面這些測試應該就很好理解了。
測試
測試一:普通 thenable 對象
const test = async () => { try { const data = await { then(resolve, reject) { resolve('hello') } } console.log(data, 'data') } catch (error) { console.log(error, 'error') } } test() // hello data
const test = async () => { try { const data = await { then(resolve, reject) { reject('hello') } } console.log(data, 'data') } catch (error) { console.log(error, 'error') } } test() // hello error
const test = async () => { await { then: r => setTimeout(r, 1000) } console.log('done') } test() // 1s 之後輸出 done
測試二:非 thenable 對象
const test = async () => { const data = await 'hello' console.log(data, 'data') } test() // hello data
const test = async () => { const data = await { a: 1 } console.log(data, 'data') } test() // { a: 1 } data
測試三:Promise 對象
const test = async () => { try { const data = await Promise.resolve('hello') console.log(data, 'data') } catch (error) { console.log(error, 'error') } } test() // hello data
const test = async () => { try { const data = await Promise.reject('hello') console.log(data, 'data') } catch (error) { console.log(error, 'error') } } test() // hello error
總結
總的來說,await 這個操作符,實際上會調用對象的 then 方法,並傳入 resolve 和 reject 參數,等我們 then 方法中調用了 resolve 或者 reject 時 await 的結果就等到了。而對於沒有 then 方法的對象或者變量,系統會自動生成一個具有 then 方法的對象(也就是Promise對象),然後將該對象或者變量作爲 resolve 的參數進行調用返回。
其實我們平時一般會把 await 理解成等到後面 Promise 的返回結果,這樣理解其實沒有什麼問題,而且覆蓋我們平時編程的絕大多數場景。但是更精細一點的理解其實應該要理解到 await 本質上是在操作對象的 then 方法(調用對象的 then 方法,並傳入 resolve、reject,並等待 then 方法去調用他們)。