JavaScript中Promise如何使用

JavaScript中Promise如何使用,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

目前創(chuàng)新互聯(lián)已為成百上千的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、渾江網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

1.什么是 Promise

promise 是目前 JS 異步編程的主流解決方案,遵循 Promises/A+ 方案。

2.Promise 原理簡(jiǎn)析

(1)promise 本身相當(dāng)于一個(gè)狀態(tài)機(jī),擁有三種狀態(tài):

  •  pending

  •  fulfilled

  •  rejected

一個(gè) promise 對(duì)象初始化時(shí)的狀態(tài)是 pending,調(diào)用了 resolve 后會(huì)將 promise 的狀態(tài)扭轉(zhuǎn)為 fulfilled,調(diào)用 reject 后會(huì)將 promise 的狀態(tài)扭轉(zhuǎn)為 rejected,這兩種扭轉(zhuǎn)一旦發(fā)生便不能再扭轉(zhuǎn)該 promise 到其他狀態(tài)。

(2)promise 對(duì)象原型上有一個(gè) then 方法,then 方法會(huì)返回一個(gè)新的 promise 對(duì)象,并且將回調(diào)函數(shù) return 的結(jié)果作為該 promise resolve 的結(jié)果,then 方法會(huì)在一個(gè) promise 狀態(tài)被扭轉(zhuǎn)為 fulfilled 或 rejected 時(shí)被調(diào)用。then 方法的參數(shù)為兩個(gè)函數(shù),分別為 promise 對(duì)象的狀態(tài)被扭轉(zhuǎn)為 fulfilled 和 rejected 對(duì)應(yīng)的回調(diào)函數(shù)。

3.Promise 如何使用

構(gòu)造一個(gè) promise 對(duì)象,并將要執(zhí)行的異步函數(shù)傳入到 promise 的參數(shù)中執(zhí)行,并且在異步執(zhí)行結(jié)束后調(diào)用 resolve( ) 函數(shù),就可以在 promise 的 then 方法中獲取到異步函數(shù)的執(zhí)行結(jié)果:

new Promise((resolve, reject) => {    setTimeout(() => {      resolve()    }, 1000)  }).then(    res => {},    err => {}  )

同時(shí)在 Promise 還為我們實(shí)現(xiàn)了很多方便使用的方法:

  •  Promise.resolve

Promise.resolve 返回一個(gè) fulfilled 狀態(tài)的 promise。

const a = Promise.resolve(1)  a.then(    res => {      // res = 1    },    err => {}  )
  •  Promise.all

Promise.all 接收一個(gè) promise 對(duì)象數(shù)組作為參數(shù),只有全部的 promise 都已經(jīng)變?yōu)?fulfilled 狀態(tài)后才會(huì)繼續(xù)后面的處理。Promise.all 本身返回的也是一個(gè) promise 。

const promise1 = new Promise((resolve, reject) => {    setTimeout(() => {      resolve('promise1')    }, 100)  })  const promise2 = new Promise((resolve, reject) => {    setTimeout(() => {      resolve('promise2')    }, 100)  })  const promises = [promise1, promise2]  Promise.all(promises).then(    res => {      // promises 全部變?yōu)?nbsp;fulfilled 狀態(tài)的處理    },    err => {      // promises 中有一個(gè)變?yōu)?nbsp;rejected 狀態(tài)的處理    }  )
  •  Promise.race

Promise.race 和 Promise.all 類(lèi)似,只不過(guò)這個(gè)函數(shù)會(huì)在 promises 中第一個(gè) promise 的狀態(tài)扭轉(zhuǎn)后就開(kāi)始后面的處理(fulfilled、rejected 均可) 。

const promise1 = new Promise((resolve, reject) => {    setTimeout(() => {      resolve('promise1')    }, 100)  })  const promise2 = new Promise((resolve, reject) => {    setTimeout(() => {      resolve('promise2')    }, 1000)  })  const promises = [promise1, promise2]  Promise.race(promises).then(    res => {      // 此時(shí)只有 promise1 resolve 了,promise2 仍處于 pending 狀態(tài)    },    err => {}  )

配合 async await 使用

現(xiàn)在的開(kāi)發(fā)場(chǎng)景中我們大多會(huì)用 async await 語(yǔ)法糖來(lái)等待一個(gè) promise 的執(zhí)行結(jié)果,使代碼的可讀性更高。async 本身是一個(gè)語(yǔ)法糖,將函數(shù)的返回值包在一個(gè) promise 中返回。

// async 函數(shù)會(huì)返回一個(gè) promise  const p = async function f() {    return 'hello world'  }  p.then(res => console.log(res)) // hello world

開(kāi)發(fā)技巧

在前端開(kāi)發(fā)上 promise 大多被用來(lái)請(qǐng)求接口,Axios 庫(kù)也是開(kāi)發(fā)中使用最頻繁的庫(kù),但是頻繁的 try catch 撲捉錯(cuò)誤會(huì)讓代碼嵌套很?chē)?yán)重??紤]如下代碼的優(yōu)化方式。

const getUserInfo = async function() {    return new Promise((resolve, reject) => {      // resolve() || reject()    })  }  // 為了處理可能的拋錯(cuò),不得不將 try catch 套在代碼外邊,一旦嵌套變多,代碼可讀性就會(huì)急劇下降  try {    const user = await getUserInfo()  } catch (e) {}

好的處理方法是在異步函數(shù)中就將錯(cuò)誤 catch,然后正常返回,如下所示 ?

const getUserInfo = async function() {    return new Promise((resolve, reject) => {      // resolve() || reject()    }).then(      res => {        return [res, null] // 處理成功的返回結(jié)果      },      err => {        return [null, err] // 處理失敗的返回結(jié)果      }    )  }  const [user, err] = await getUserInfo()  if (err) {    // err 處理  }  // 這樣的處理是不是清晰了很多呢

4.Promise 源碼實(shí)現(xiàn)

知識(shí)的學(xué)習(xí)需要知其然且知其所以然,所以通過(guò)一點(diǎn)點(diǎn)實(shí)現(xiàn)的一個(gè) promise 能夠?qū)?promise 有著更深刻的理解。

(1)首先按照最基本的 promise 調(diào)用方式實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 promise (基于 ES6 規(guī)范編寫(xiě)),假設(shè)我們有如下調(diào)用方式:

new Promise((resolve, reject) => {    setTimeout(() => {      resolve(1)    }, 1000)  })    .then(      res => {        console.log(res)        return 2      },      err => {}    )    .then(      res => {        console.log(res)      },      err => {}    )

我們首先要實(shí)現(xiàn)一個(gè) Promise 的類(lèi),這個(gè)類(lèi)的構(gòu)造函數(shù)會(huì)傳入一個(gè)函數(shù)作為參數(shù),并且向該函數(shù)傳入 resolve 和 reject 兩個(gè)方法。

初始化 Promise 的狀態(tài)為 pending。

class MyPromise {    constructor(executor) {      this.executor = executor      this.value = null      this.status = 'pending'      const resolve = value => {        if (this.status === 'pending') {          this.value = value          // 調(diào)用 resolve 后記錄 resolve 的值          this.status = 'fulfilled'   // 調(diào)用 resolve 扭轉(zhuǎn) promise 狀態(tài)        }      }      const reject = value => {        if (this.status === 'pending') {          this.value = value          // 調(diào)用 reject 后記錄 reject 的值          this.status = 'rejected'    // 調(diào)用 reject 扭轉(zhuǎn) promise 狀態(tài)        }      }      this.executor(resolve, reject)    }

(2)接下來(lái)要實(shí)現(xiàn) promise 對(duì)象上的 then 方法,then 方法會(huì)傳入兩個(gè)函數(shù)作為參數(shù),分別作為 promise 對(duì)象 resolve 和 reject 的處理函數(shù)。

這里要注意三點(diǎn):

  •  then 函數(shù)需要返回一個(gè)新的 promise 對(duì)象

  •  執(zhí)行 then 函數(shù)的時(shí)候這個(gè) promise 的狀態(tài)可能還沒(méi)有被扭轉(zhuǎn)為 fulfilled 或 rejected

  •  一個(gè) promise 對(duì)象可以同時(shí)多次調(diào)用 then 函數(shù) 

class MyPromise {    constructor(executor) {      this.executor = executor      this.value = null      this.status = 'pending'      this.onFulfilledFunctions = [] // 存放這個(gè) promise 注冊(cè)的 then 函數(shù)中傳的第一個(gè)函數(shù)參數(shù)      this.onRejectedFunctions = [] // 存放這個(gè) promise 注冊(cè)的 then 函數(shù)中傳的第二個(gè)函數(shù)參數(shù)      const resolve = value => {        if (this.status === 'pending') {          this.value = value          this.status = 'fulfilled'          this.onFulfilledFunctions.forEach(onFulfilled => {            onFulfilled() // 將 onFulfilledFunctions 中的函數(shù)拿出來(lái)執(zhí)行          })        }      }      const reject = value => {        if (this.status === 'pending') {          this.value = value          this.status = 'rejected'          this.onRejectedFunctions.forEach(onRejected => {            onRejected() // 將 onRejectedFunctions 中的函數(shù)拿出來(lái)執(zhí)行          })        }      }      this.executor(resolve, reject)    }    then(onFulfilled, onRejected) {      const self = this      if (this.status === 'pending') {        /**         *  當(dāng) promise 的狀態(tài)仍然處于 ‘pending’ 狀態(tài)時(shí),需要將注冊(cè) onFulfilled、onRejected 方法放到 promise 的 onFulfilledFunctions、onRejectedFunctions 備用         */        return new MyPromise((resolve, reject) => {          this.onFulfilledFunctions.push(() => {            const thenReturn = onFulfilled(self.value)            resolve(thenReturn)          })          this.onRejectedFunctions.push(() => {            const thenReturn = onRejected(self.value)            resolve(thenReturn)          })        })      } else if (this.status === 'fulfilled') {        return new MyPromise((resolve, reject) => {          const thenReturn = onFulfilled(self.value)          resolve(thenReturn)        })      } else {        return new MyPromise((resolve, reject) => {          const thenReturn = onRejected(self.value)          resolve(thenReturn)        })      }    }  }

對(duì)于以上完成的 MyPromise 進(jìn)行測(cè)試,測(cè)試代碼如下:

const p = new MyPromise((resolve, reject) => {    setTimeout(() => {      resolve(1)    }, 1000)  })  p.then(res => {    console.log('first then', res)    return res + 1  }).then(res => {    console.log('first then', res)  })  p.then(res => {    console.log(`second then`, res)    return res + 1  }).then(res => {    console.log(`second then`, res)  })  /**   *  輸出結(jié)果如下:   *  first then 1   *  first then 2   *  second then 1   *  second then 2   */

(3)在 promise 相關(guān)的內(nèi)容中,有一點(diǎn)常常被我們忽略,當(dāng) then 函數(shù)中返回的是一個(gè) promise 應(yīng)該如何處理?

考慮如下代碼:

// 使用正確的 Promise  new Promise((resolve, reject) => {    setTimeout(() => {      resolve()    }, 1000)  })    .then(res => {      console.log('外部 promise')      return new Promise((resolve, reject) => {        resolve(`內(nèi)部 promise`)      })    })    .then(res => {      console.log(res)    })  /**   * 輸出結(jié)果如下:   * 外部 promise   * 內(nèi)部 promise   */

通過(guò)以上的輸出結(jié)果不難判斷,當(dāng) then 函數(shù)返回的是一個(gè) promise 時(shí),promise 并不會(huì)直接將這個(gè) promise 傳遞到下一個(gè) then 函數(shù),而是會(huì)等待該 promise resolve 后,將其 resolve 的值,傳遞給下一個(gè) then 函數(shù),找到我們實(shí)現(xiàn)的代碼的 then 函數(shù)部分,做以下修改:

then(onFulfilled, onRejected) {      const self = this      if (this.status === 'pending') {          return new MyPromise((resolve, reject) => {          this.onFulfilledFunctions.push(() => {              const thenReturn = onFulfilled(self.value)              if (thenReturn instanceof MyPromise) {                  // 當(dāng)返回值為 promise 時(shí),等該內(nèi)部的 promise 狀態(tài)扭轉(zhuǎn)時(shí),同步扭轉(zhuǎn)外部的 promise 狀態(tài)                  thenReturn.then(resolve, reject)              } else {                  resolve(thenReturn)              }          })          this.onRejectedFunctions.push(() => {              const thenReturn = onRejected(self.value)              if (thenReturn instanceof MyPromise) {                  // 當(dāng)返回值為 promise 時(shí),等該內(nèi)部的 promise 狀態(tài)扭轉(zhuǎn)時(shí),同步扭轉(zhuǎn)外部的 promise 狀態(tài)                  thenReturn.then(resolve, reject)              } else {                  resolve(thenReturn)              }          })          })      } else if (this.status === 'fulfilled') {          return new MyPromise((resolve, reject) => {              const thenReturn = onFulfilled(self.value)              if (thenReturn instanceof MyPromise) {                  // 當(dāng)返回值為 promise 時(shí),等該內(nèi)部的 promise 狀態(tài)扭轉(zhuǎn)時(shí),同步扭轉(zhuǎn)外部的 promise 狀態(tài)                  thenReturn.then(resolve, reject)              } else {                  resolve(thenReturn)              }          })      } else {          return new MyPromise((resolve, reject) => {              const thenReturn = onRejected(self.value)              if (thenReturn instanceof MyPromise) {                  // 當(dāng)返回值為 promise 時(shí),等該內(nèi)部的 promise 狀態(tài)扭轉(zhuǎn)時(shí),同步扭轉(zhuǎn)外部的 promise 狀態(tài)                  thenReturn.then(resolve, reject)              } else {                  resolve(thenReturn)              }          })      }  }

(4) 之前的 promise 實(shí)現(xiàn)代碼仍然缺少很多細(xì)節(jié)邏輯,下面會(huì)提供一個(gè)相對(duì)完整的版本,注釋部分是增加的代碼,并提供了解釋。

class MyPromise {    constructor(executor) {      this.executor = executor      this.value = null      this.status = 'pending'      this.onFulfilledFunctions = []      this.onRejectedFunctions = []      const resolve = value => {        if (this.status === 'pending') {          this.value = value          this.status = 'fulfilled'          this.onFulfilledFunctions.forEach(onFulfilled => {            onFulfilled()          })        }      }      const reject = value => {        if (this.status === 'pending') {          this.value = value          this.status = 'rejected'          this.onRejectedFunctions.forEach(onRejected => {            onRejected()          })        }      }      this.executor(resolve, reject)    }    then(onFulfilled, onRejected) {      const self = this      if (typeof onFulfilled !== 'function') {        // 兼容 onFulfilled 未傳函數(shù)的情況        onFulfilled = function() {}      }      if (typeof onRejected !== 'function') {        // 兼容 onRejected 未傳函數(shù)的情況        onRejected = function() {}      }      if (this.status === 'pending') {        return new MyPromise((resolve, reject) => {          this.onFulfilledFunctions.push(() => {            try {              const thenReturn = onFulfilled(self.value)              if (thenReturn instanceof MyPromise) {                thenReturn.then(resolve, reject)              } else {                resolve(thenReturn)              }            } catch (err) {              // catch 執(zhí)行過(guò)程的錯(cuò)誤              reject(err)            }          })          this.onRejectedFunctions.push(() => {            try {              const thenReturn = onRejected(self.value)              if (thenReturn instanceof MyPromise) {                thenReturn.then(resolve, reject)              } else {                resolve(thenReturn)              }            } catch (err) {              // catch 執(zhí)行過(guò)程的錯(cuò)誤              reject(err)            }          })        })      } else if (this.status === 'fulfilled') {        return new MyPromise((resolve, reject) => {          try {            const thenReturn = onFulfilled(self.value)            if (thenReturn instanceof MyPromise) {              thenReturn.then(resolve, reject)            } else {              resolve(thenReturn)            }          } catch (err) {            // catch 執(zhí)行過(guò)程的錯(cuò)誤            reject(err)          }        })      } else {        return new MyPromise((resolve, reject) => {          try {            const thenReturn = onRejected(self.value)            if (thenReturn instanceof MyPromise) {              thenReturn.then(resolve, reject)            } else {              resolve(thenReturn)            }          } catch (err) {            // catch 執(zhí)行過(guò)程的錯(cuò)誤            reject(err)          }        })      }    }  }

(5)至此一個(gè)相對(duì)完整的 promise 已經(jīng)實(shí)現(xiàn),但他仍有一些問(wèn)題,了解宏任務(wù)、微任務(wù)的同學(xué)一定知道,promise 的 then 函數(shù)實(shí)際上是注冊(cè)一個(gè)微任務(wù),then 函數(shù)中的參數(shù)函數(shù)并不會(huì)同步執(zhí)行。

查看如下代碼:

new Promise((resolve,reject)=>{      console.log(`promise 內(nèi)部`)      resolve()  }).then((res)=>{      console.log(`第一個(gè) then`)  })  console.log(`promise 外部`)  /**   * 輸出結(jié)果如下:   * promise 內(nèi)部   * promise 外部   * 第一個(gè) then   */  // 但是如果使用我們寫(xiě)的 MyPromise 來(lái)執(zhí)行上面的程序  new MyPromise((resolve,reject)=>{      console.log(`promise 內(nèi)部`)      resolve()  }).then((res)=>{      console.log(`第一個(gè) then`)  })  console.log(`promise 外部`)  /**   * 輸出結(jié)果如下:   * promise 內(nèi)部   * 第一個(gè) then   * promise 外部   */

以上的原因是因?yàn)榈奈覀兊?then 中的 onFulfilled、onRejected 是同步執(zhí)行的,當(dāng)執(zhí)行到 then 函數(shù)時(shí)上一個(gè) promise 的狀態(tài)已經(jīng)扭轉(zhuǎn)為 fulfilled 的話就會(huì)立即執(zhí)行 onFulfilled、onRejected。

要解決這個(gè)問(wèn)題也非常簡(jiǎn)單,將 onFulfilled、onRejected 的執(zhí)行放在下一個(gè)事件循環(huán)中就可以了。

if (this.status === 'fulfilled') {    return new MyPromise((resolve, reject) => {      setTimeout(() => {        try {          const thenReturn = onFulfilled(self.value)          if (thenReturn instanceof MyPromise) {            thenReturn.then(resolve, reject)          } else {            resolve(thenReturn)          }        } catch (err) {          // catch 執(zhí)行過(guò)程的錯(cuò)誤          reject(err)        }      })    }, 0)  }

關(guān)于宏任務(wù)和微任務(wù)的解釋?zhuān)以诰蚪鹕峡吹竭^(guò)一篇非常棒的文章,它用銀行柜臺(tái)的例子解釋了為什么會(huì)同時(shí)存在宏任務(wù)和微任務(wù)兩個(gè)隊(duì)列,文章鏈接貼到文末感興趣的可以看一下。

5.Promise/A+ 方案解讀

我們上面實(shí)現(xiàn)的一切邏輯,均是按照 Promise/A+ 規(guī)范實(shí)現(xiàn)的,Promise/A+ 規(guī)范說(shuō)的大部分內(nèi)容已經(jīng)在上面 promise 的實(shí)現(xiàn)過(guò)程中一一講解。接下來(lái)講述相當(dāng)于一個(gè)匯總:

    1.  promise 有三個(gè)狀態(tài) pending、fulfilled、rejected,只能由 pending 向 fulfilled 、rejected 兩種狀態(tài)發(fā)生改變。

    2.  promise 需要提供一個(gè) then 方法,then 方法接收 (onFulfilled,onRejected) 兩個(gè)函數(shù)作為參數(shù)。

    3.  onFulfilled、onRejected 須在 promise 完成后后(狀態(tài)扭轉(zhuǎn))后調(diào)用,且只能調(diào)用一次。

    4.  onFulfilled、onRejected 僅僅作為函數(shù)進(jìn)行調(diào)用,不能夠?qū)?this 指向調(diào)用它的 promise。

    5.  onFulfilled、onRejected 必須在執(zhí)行上下文棧只包含平臺(tái)代碼后才能執(zhí)行。平臺(tái)代碼指 引擎,環(huán)境,Promise 實(shí)現(xiàn)代碼。(PS:這處規(guī)范要求 onFulfilled、onRejected 函數(shù)的執(zhí)行必須在 then 被調(diào)用的那個(gè)事件循環(huán)之后的事件循環(huán)。但是規(guī)范并沒(méi)有要求是把它們作為一個(gè)微任務(wù)或是宏任務(wù)去執(zhí)行,只是各平臺(tái)的實(shí)現(xiàn)均把 Promise 的 onFulfilled、onRejected 放到微任務(wù)隊(duì)列中去執(zhí)行了)。

    6.  onFulfilled、onRejected 必須是個(gè)函數(shù),否則忽略。

    7.  then 方法可以被一個(gè) promise 多次調(diào)用。

    8.  then 方法需要返回一個(gè) promise。

    9.  Promise 的解析過(guò)程是一個(gè)抽象操作,將 Promise 和一個(gè)值作為輸入,我們將其表示為 [[Resolve]](promise,x), [[Resolve]](promise,x) 是創(chuàng)建一個(gè) Resolve 方法并傳入 promise,x(promise 成功時(shí)返回的值) 兩個(gè)參數(shù),如果 x 是一個(gè) thenable 對(duì)象(含有 then 方法),并且假設(shè) x 的行為類(lèi)似 promise, [[Resolve]](promise,x) 會(huì)創(chuàng)造一個(gè)采用 x 狀態(tài)的 promise,否則 [[Resolve]](promise,x) 會(huì)用 x 來(lái)扭轉(zhuǎn) promise 的狀態(tài)。取得輸入的不同的 promise 實(shí)現(xiàn)方式可以進(jìn)行交互,只要它們都暴露了 Promise/A+ 兼容方法即可。它也允許 promise 使用合理的 then 方法同化一些不合規(guī)范的 promise 實(shí)現(xiàn)。

第 9 點(diǎn)只看文檔比較晦澀難懂,其實(shí)它是針對(duì)我們的 then 方法中的這行代碼做的規(guī)范解釋。

return new MyPromise((resolve, reject) => {    try {      const thenReturn = onFulfilled(self.value)      if (thenReturn instanceof MyPromise) {        // ? 就是這一行代碼        thenReturn.then(resolve, reject)      } else {        resolve(thenReturn)      }    } catch (err) {      reject(err)    }  })

因?yàn)?Promise 并不是 JS 一開(kāi)始就有的標(biāo)準(zhǔn),是被很多第三方獨(dú)立實(shí)現(xiàn)的一個(gè)方法,所以無(wú)法通過(guò) instanceof 來(lái)判斷返回值是否是一個(gè) promise 對(duì)象,所以為了使不同的 promise 可以交互,才有了我上面提到的第 9 條規(guī)范。當(dāng)返回值 thenReturn 是一個(gè) promise 對(duì)象時(shí),我們需要等待這個(gè) promise 的狀態(tài)發(fā)生扭轉(zhuǎn)并用它的返回值來(lái) resolve 外層的 promise。

所以最后我們還需要實(shí)現(xiàn) [[Resolve]](promise,x),來(lái)滿足 promise 規(guī)范,規(guī)范如下所示。

JavaScript中Promise如何使用

/**   * resolvePromise 函數(shù)即為根據(jù) x 的值來(lái)決定 promise2 的狀態(tài)的函數(shù)   * @param {Promise} promise2  then 函數(shù)需要返回的 promise 對(duì)象   * @param {any} x onResolve || onReject 執(zhí)行后得到的返回值   * @param {Function} resolve  MyPromise 中的 resolve 方法   * @param {Function} reject  MyPromise 中的 reject 方法   */  function resolvePromise(promise2, x, resolve, reject) {    if (promise2 === x) {      // 2.3.1 promise2 和 x 指向同一個(gè)對(duì)象      reject(new TypeError())      return    }    if (x instanceof MyPromise) {      // 2.3.2 x 是一個(gè) MyPromise 的實(shí)例,采用他的狀態(tài)      if (x.status === 'pending') {        x.then(          value => {            resolvePromise(promise2, value, resolve, reject)          },          err => {            reject(err)          }        )      } else {        x.then(resolve, reject)      }      return    }    if (x && (typeof x === 'function' || typeof x === 'object')) {      // 2.3.3 x 是一個(gè)對(duì)象或函數(shù)      try {        const then = x.then // 2.3.3.1 聲明 變量 then = x.then        let promiseStatusConfirmed = false // promise 的狀態(tài)確定        if (typeof then === 'function') {          // 2.3.3.3 then 是一個(gè)方法,把 x 綁定到 then 函數(shù)中的 this 上并調(diào)用          then.call(            x,            value => {              // 2.3.3.3.1 then 函數(shù)返回了值 value,則使用 [[Resolve]](promise, value),用于監(jiān)測(cè) value 是不是也是一個(gè) thenable 的對(duì)象              if (promiseStatusConfirmed) return // 2.3.3.3.3 即這三處誰(shuí)選執(zhí)行就以誰(shuí)的結(jié)果為準(zhǔn)              promiseStatusConfirmed = true              resolvePromise(promise2, value, resolve, reject)              return            },            err => {              // 2.3.3.3.2  then 函數(shù)拋錯(cuò) err ,用 err reject 當(dāng)前的 promise              if (promiseStatusConfirmed) return // 2.3.3.3.3 即這三處誰(shuí)選執(zhí)行就以誰(shuí)的結(jié)果為準(zhǔn)              promiseStatusConfirmed = true              reject(err)              return            }          )        } else {          // 2.3.3.4  then 不是一個(gè)方法,則用 x 扭轉(zhuǎn) promise 狀態(tài) 為 fulfilled          resolve(x)        }      } catch (e) {        // 2.3.3.2 在取得 x.then 的結(jié)果時(shí)拋出錯(cuò)誤 e 的話,使用 e reject 當(dāng)前的 promise        if (promiseStatusConfirmed) return // 2.3.3.3.3 即這三處誰(shuí)選執(zhí)行就以誰(shuí)的結(jié)果為準(zhǔn)        promiseStatusConfirmed = true        reject(e)        return      }    } else {      resolve(x) // 2.3.4 如果 x 不是 object || function,用 x 扭轉(zhuǎn) promise 狀態(tài) 為 fulfilled    }  }

然后我們就可以用 resolcePromise 方法替換之前的這部分代碼。

return new MyPromise((resolve, reject) => {    try {      const thenReturn = onFulfilled(self.value)      if (thenReturn instanceof MyPromise) {        thenReturn.then(resolve, reject)      } else {        resolve(thenReturn)      }    } catch (err) {      reject(err)    }  })  // 變成下面這樣 ?   return new MyPromise((resolve, reject) => {    try {      const thenReturn = onFulfilled(self.value)      resolvePromise(resolve,reject)    } catch (err) {      reject(err)    }  })

關(guān)于JavaScript中Promise如何使用問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

新聞名稱(chēng):JavaScript中Promise如何使用
鏈接分享:http://muchs.cn/article6/gdsdog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化網(wǎng)站建設(shè)、ChatGPT、虛擬主機(jī)、動(dòng)態(tài)網(wǎng)站、網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)