await 到底在等什麼?

核心

其實 await 本質上等的是:後面的 thenable 對象的 then 方法調用 resolve 或者 reject。

這裏面其實包含三個細節:

  1. thenable 對象其實就是包含 then 方法的普通對象。
  2. 如果 await 後面的對象不是一個 thenable 對象,那麼系統會將它包裝成 thenable 對象。
  3. 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 方法去調用他們)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章