<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      JS基于Promises/A+規范實現一個Promise

       ??本文基于Promises/A+實現一個Promise對象,幫助大家理解使用它。

      ??說明一下,Promises/A+是ES6中Promise的前身,規范可以參考:https://promisesaplus.com/

      ??ES6白皮書參考地址:https://tc39.es/ecma262/#sec-promise-objects

      ??MDN文檔:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

      ??首先,根據Promises/A+規范,定義了一些術語,重要的就Promise和Thenable:??

          Promise是一個具有then方法的對象或者函數,這個then方法需要滿足后面的一些規范。
          Thenable是一個具有then方法的對象或者函數。

      ??從上面的術語可以看到,PromiseThenable,但是Thenable不一定是Promise,主要區別有兩點:

      ??1. Promise對象具有三個狀態:pending, fulfilled, rejected??

          1、當狀態是pending時,Promise的狀態可以變為fulfilled或者rejected。
          2、當狀態是fulfilled時,Promise的狀態不可再改變,并具有一個不可改變的結果,結果可以是null、undefined、對象、函數、Promise或者Thenable等。
          3、當狀態是rejected時,Promise的狀態不可再改變,并可具有一個不可改變的原因,原因可以是null、undefined、對象、函數、Promise或者Thenable等。

       ??2. Promise對象需要提供一個then方法,這個then方法需要接收兩個參數: ??

          promise.then(onFulfilled, onRejected)
          
          //onFulfilled是當promise狀態從pending變為fulfilled后需要執行的函數
          //onRejected是當promise狀態從pending變為rejected后需要執行的函數

      ??而在ES6的規范中,Promise不僅滿足上面Promises/A+規范,還有其他一些特性來保證Promise的實用性,比如ES6中,Promise的構造函數需要傳入一個executor函數參數,它接收兩個函數作為參數:resolveFunc rejectFunc,分別表示將Promise的狀態置為fulfilled還是rejected,因此,我們可以寫出Promise的構造函數大概是這個樣子的:

          class MyPromise {
              constructor(executor) {
                  //表示狀態是否已指定,保證狀態只會被改變一次
                  let specified = false
                  //狀態
                  let state = PENDING
                  //結果或者原因
                  let value = void 0
      
                  //fulfilled狀態的回調函數
                  let onFulfilledCallbacks = []
                  //rejected狀態的回調函數
                  let onRejectedCallbacks = []
      
                  //resolve函數,改變狀態為fulfilled
                  const resolve = (result) => { }
                  //reject函數,改變狀態為rejected
                  const reject = (reason) => { }
      
                  //then方法
                  this.then = (onFulfilled, onRejected) => { }
      
                  try {
                      executor(resolve, reject)
                  } catch (error) {
                      reject(error) //如果executor拋出異常,那么直接reject
                  }
              }
          }

      ??上面只是Promise大致的樣子,接下來我們就需要去實現這幾個函數即可:resolve、rejectthen方法

      ??首先,我們需要先定義一些通用的函數與變量:??

          //Promise的三個狀態
          const PENDING = 'pending'
          const FULFILLED = 'fulfilled'
          const REJECTED = 'rejected'
          //判斷一個值是否是一個函數
          const isFunction = value => value && typeof value === 'function' && value instanceof Function
          //判斷一個值是否是一個Promise
          const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
          //判斷一個值是否是一個對象
          const isObject = value => value && typeof value === 'object' && value instanceof Object
          //執行微任務,沒有返回結果
          function runMicroTask(fn) {
              //首先看微任務隊列函數是否存在,如果存在則使用微任務隊列執行
              if (isFunction(queueMicrotask)) {
                  runMicroTask = f => queueMicrotask(f)
              } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js環境
                  runMicroTask = f => process.nextTick(f)
              } else if (isFunction(MutationObserver)) { //如果是瀏覽器環境
                  runMicroTask = f => {
                      const observer = new MutationObserver(f)
                      const node = document.createTextNode('')
                      observer.observe(node, { characterData: true })
                      node.data = '1' //觸發MutationObserver
                  }
              } else { //如果都不存在,那么使用setTimeout(fn, 0)執行
                  runMicroTask = f => setTimeout(f, 0)
              }
              runMicroTask(fn)
          }

      ??reject函數

      ??reject函數的視線很簡單,就是變更Promise的狀態和結果即可,結果往往是一個Error對象:??

          //reject函數,改變狀態為rejected
          const reject = (reason) => {
              //當且僅當狀態是pending且未指定時進入
              if (state === PENDING && !specified) {
                  [state, value, specified] = [REJECTED, reason, true]
      
                  //rejected狀態的回調函數,將其添加到onRejectedCallbacks數組中,判斷是否執行回調函數
                  runOrQueueTasks(onRejectedCallbacks, REJECTED)
              }
          }

      ??這里runOrQueueTasks其實就是將回調函數放到微任務里并準備執行回調函數,實現如下:??

          const runOrQueueTasks = (callbacks, requireState, callback) => {
              //如果callback是函數,那么將其添加到callbacks數組中
              callback && callbacks.push(callback)
              //如果是指定狀態,那么使用微任務執行
              if (state === requireState) {
                  while (callbacks.length) {
                      const cb = callbacks.shift()
                      runMicroTask(() => cb(value)) // 使用微任務執行
                  }
              }
          }

      ??resolve函數

      ??resolve的函數實現邏輯更多一些,具體可以看看MDN的說明(跳轉),總結下來就是:??

          1、resolve函數接收一個結果對象result
          2、如果result結果對象是當前Promise自身,那么將會reject一個TypeError
          3、如果result結果對象不是一個Thenable對象,那么Promise將會被立即FULFILLED,并采用這個result作為結果
          4、如果result結果對象是一個Thenable對象,那么將會把Thenable對象的then方法放到微任務去執行,并Promise的resolve和reject作為then方法的兩個參數傳進入(近似可以這么認為),就是說Promise的結果又Thenable決定

      ??因此我們的resolve函數大概是這個樣子的:??

          //resolve函數,改變狀態為fulfilled
          const resolve = (result) => {
              //當且僅當狀態是pending且未指定時進入
              if (state === PENDING && !specified) {
                  //如果傳入的是當前Promise對象,那么直接reject
                  if (result === this) {
                      return reject(new TypeError('Chaining cycle detected for promise'))
                  }
                  specified = true;
      
                  //如果result是Thenable,那么調用(ES6白皮書)
                  //如果result是一個Promise,那么吸收它的狀態
                  try {
                      if (result && isFunction(result.then)) {
                          return runMicroTask(() => {
                              try {
                                  const res = r => (specified = false, resolve(r)) //臨時打開
                                  const rej = r => (specified = false, reject(r))  //臨時打開             
                                  result.then(res, rej)
                              } catch (error) {
                                  reject(error)
                              }
                          })
                      }
                  } catch (error) {
                     return reject(error) //如果result.then拋出異常,那么直接reject
                  }
      
                  [state, value] = [FULFILLED, result]
      
                  //fulfilled狀態的回調函數,將其添加到onFulfilledCallbacks數組中,判斷是否執行回調函數
                  runOrQueueTasks(onFulfilledCallbacks, FULFILLED)
              }
          }

      ??then方法 

      ??根據Promises/A+規范,then方法需要滿足下面的:??

          1、調用方式:promise.then(onFulfilled, onRejected),這里onFulfilled、onRejected都必須是函數,否則將被忽略
          2、onFulfilled、onRejected需要分別在promise變為fulfilled和rejected后執行,將結果或者原因作為第一個參數傳入,并且至多執行一次
          3、onFulfilled、onRejected不能在當前上下文中執行,需要放到setTimeout、微任務這樣的上下文去執行
          4、then方法如果調用多次,onFulfilled和onRejected需要按他們所在的then方法的調用順序依次執行
          5、then方法方法需要返回一個新的Promise對象:promise2 = promise1.then(onFulfilled, onRejected)
              1、如果onFulfilled和onRejected返回一個值x,那么將執行Promise Resolution Procedure,將promise2和x作為參數傳入
              2、如果onFulfilled或者onRejected拋出異常,那么promise2將會使用這個異常進行reject
              3、如果onFulfilled不是函數且promise1狀態是fulfilled,或者onRejected不是函數且promise1狀態是rejected,那么promise2將會吸收promise1的狀態,即promise1和promise2保持相同的結果和狀態

       ??因為then方法的實現大致如下

          //then方法
          this.then = (onFulfilled, onRejected) => {
              const promise = new (this.constructor[Symbol.species] || MyPromise)((resolve, reject) => {
                  //如果onFulfilled是函數則調用
                  state !== REJECTED && runOrQueueTasks(onFulfilledCallbacks, FULFILLED, isFunction(onFulfilled) ? value => {
                      try {
                          const x = onFulfilled(value)
                          //根據函數返回結果進行Promise Resolution Procedure過程
                          promiseResolutionProcedure(promise, x, resolve, reject)
                      } catch (error) {
                          reject(error)
                      }
                  } : resolve)//否則根據當前狀態直接resolve
      
                  //如果onRejected是函數則調用
                  state !== FULFILLED && runOrQueueTasks(onRejectedCallbacks, REJECTED, isFunction(onRejected) ? value => {
                      try {
                          const x = onRejected(value)
                          //根據函數返回結果進行Promise Resolution Procedure過程
                          promiseResolutionProcedure(promise, x, resolve, reject)
                      } catch (error) {
                          reject(error)
                      }
                  } : reject)//否則根據當前狀態直接reject
              })
              return promise
          }

       ??這里說下Promise Resolution Procedure過程

          Promise Resolution Procedure過程采用這個表達方式:[[Resolve]](promise, x),其實可以理解為就是個函數處理過程,表示promise怎么去根據x的值變更狀態
          1、如果promise和x是相同的對象,那么promise將會被reject(TypeError)
          2、如果x是一個Promise,那么promise對象將會吸收x的狀態,即promise和x保持相同的結果和狀態
          3、如果x是一個Thenable,那么調用Thenable的then方法,并將promise的resolve和reject函數作為參數傳入then方法調用
              1、如果resolve函數被調用,并接收到結果y,那么接著執行Promise Resolution Procedure過程:[[Resolve]](promise, y)
              2、如果reject函數被調用,那么接收到結果r,那么promise將會被reject(r)
              3、resolve和reject函數只能被調用一次
              4、如果then方法調用報錯,且resolve和reject函數都未被調用,那么promise將會被reject
          4、否則promise將會被resolve(x)

      ??大致的實現代碼是這個樣子的:??

          //Promise狀態處理過程
          const promiseResolutionProcedure = (promise, x, resolve, reject) => {
              // promise和x不能引用同一個對象
              if (promise === x) {
                  throw new TypeError('Chaining cycle detected for promise')
              }
      
              //如果x是一個Promise,那么promise對象直接吸收x的狀態
              if (isPromise(x)) { //這里兼容一下原生Promise
                  //這里ES6白皮書是放到微隊列中執行的(PromiseA+規范沒有確定)
                  return runMicroTask(() => x.then(resolve, reject))
              }
      
              //如果x是對象或者函數
              if (isObject(x) || isFunction(x)) {
                  let ignoreCall = false
                  try {
                      //取then方法報錯,那么直接reject
                      let then = x.then
                      //如果then是一個函數,那么調用then方法
                      if (isFunction(then)) {
                          //調用采用x作為this,并傳入兩個參數resolve和reject,并要求resolve和reject只能調用一次 
                          return runMicroTask(() => then.call(x, y => {
                              ignoreCall = ignoreCall || !promiseResolutionProcedure(promise, y, resolve, reject)
                          }, r => {
                              ignoreCall = ignoreCall || !reject(r)
                          }))
                      }
                  } catch (error) {
                      //如果then方法已經調用了resolve或reject,那么直接忽略
                      ignoreCall || reject(error)
                  }
              }
              //如果x不是一個對象或者函數,那么直接resolve
              resolve(x)
          }

       ??注:這里then方法的實現是參考Promises/A+規范,MDN上的描述大致含義和這個差不多,感興趣的可以去看看跳轉

      ??到這里我們的Promise就已經實現了,接下來說說Promise其它方法的拓展,這部分不是Promises/A+規范的內容,是ES6的Promise的拓展

      ??catch函數

      ??catch函數可以參考MDN上面的說明(跳轉),而我們的實現如下:??

          class MyPromise {
              //...其它代碼
              
              //以下是ES6白皮書的拓展,不是Promise A+規范的內容
              catch(onRejected) {
                  return this.then(null, onRejected)
              }
          }

      ??finally函數

      ??finally函數可以參考MDN上面的說明(跳轉),而我們的實現如下:

          class MyPromise {
              //...其它代碼
              
              finally(onFinally) {
                  //onFinally是一個不接收任何參數的函數
                  //如果 onFinally 拋出錯誤或返回被拒絕的 promise,則新的 promise 將使用該值進行拒絕
                  const onThen = isFunction(onFinally)?() => {
                      const result = onFinally()
                      if (isPromise(result)) {
                          return result.then(() => this, () => result)
                      }
                      return this;
                  } : onFinally
                  return this.then(onThen, onThen)
              }
          }

      ??resolve函數

      ??resolve函數可以參考MDN上面的說明(跳轉),而我們的實現如下:??

          class MyPromise {
              //...其它代碼
              
              static resolve(value) {
                  //如果value是一個Promise,那么直接返回
                  if (isPromise(value)) {
                      return value
                  }
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, resolve } = MyPromise.withResolvers.call(this)
                  resolve(value) //直接resolve
                  return promise
              }
          }

      ??reject函數

      ??reject函數可以參考MDN上面的說明(跳轉),而我們的實現如下:?

          class MyPromise {
              //...其它代碼
              
              static reject(reason) {
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, reject } = MyPromise.withResolvers.call(this)
                  reject(reason) //直接reject
                  return promise
              }
          }

      ??all函數

      ??all函數可以參考MDN上面的說明(跳轉),而我們的實現如下:?

          class MyPromise {
              //...其它代碼
              
              static all(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  const results = []
                  //如果是空數組,那么直接返回一個resolved的Promise
                  if (!promises.length) {
                      resolve(results)
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(value => {
                              results[i] = value
                              promises.pop() //每執行完成就彈出一個進行計數
                              //如果全部已經是fulfilled狀態,那么resolve結果
                              promises.length || resolve(results)
                          }, reject)
                      })
                  }
                  return promise
              }
          }

      ??race函數

      ??race函數可以參考MDN上面的說明(跳轉),而我們的實現如下:

          class MyPromise {
              //...其它代碼
              
              static race(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  //只要有一個是fulfilled或者rejected,那么當前Promise就需要改變狀態
                  promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))
                  return promise
              }
          }

      ??allSettled函數

      ??allSettled函數可以參考MDN上面的說明(跳轉),而我們的實現如下:

          class MyPromise {
              //...其它代碼
              
              static allSettled(promises) {
                  promises = [...promises]
                  const { promise, resolve } = MyPromise.withResolvers()
                  const results = []
                  //如果是空數組,那么直接返回一個resolved的Promise
                  if (!promises.length) {
                      resolve(results)
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(value => {
                              results[i] = { status: FULFILLED, value }
                              promises.pop() //每執行完成就彈出一個進行計數
                              //全部Promise已經是fulfilled或者rejected狀態了,那么resolve
                              promises.length || resolve(results)
                          }, reason => {
                              results[i] = { status: REJECTED, reason }
                              promises.pop() //每執行完成就彈出一個進行計數
                              //全部Promise已經是fulfilled或者rejected狀態了,那么resolve
                              promises.length || resolve(results)
                          })
                      })
                  }
                  return promise
              }
          }

      ??any函數

      ??any函數可以參考MDN上面的說明(跳轉),而我們的實現如下:

          class MyPromise {
              //...其它代碼
              
              static any(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  const errors = []
                  //如果是空數組,那么直接返回一個rejected的Promise
                  if (!promises.length) {
                      reject(new AggregateError(errors, 'All promises were rejected'))
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(resolve, reason => {
                              errors[i] = reason
                              promises.pop() //每執行完成就彈出一個進行計數
                              //如果有rejected,那么收集所有rejected并最后全局reject
                              promises.length || reject(new AggregateError(errors, 'All promises were rejected'))
                          })
                      })
                  }
                  return promise
              }
          }

      ??try函數

      ??try函數可以參考MDN上面的說明(跳轉),而我們的實現如下:??

          class MyPromise {
              //...其它代碼
              
              static try(fn, ...args) {
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, resolve, reject } = MyPromise.withResolvers.call(this)
                  try {
                      const result = fn(...args)
                      resolve(result)
                  } catch (error) {
                      reject(error)
                  }
                  return promise
              }
          }

      ??withResolvers函數

      ??withResolvers函數可以參考MDN上面的說明(跳轉),而我們的實現如下:

          class MyPromise {
              //...其它代碼
              
              static withResolvers() {
                  let resolve, reject
                  const promise = new this((res, rej) => {
                      resolve = res
                      reject = rej
                  })
                  return { promise, resolve, reject }
              }
          }

      ??最后附上自己實現的Promise完整代碼:

      查看代碼
          //Promise的三個狀態
          const PENDING = 'pending'
          const FULFILLED = 'fulfilled'
          const REJECTED = 'rejected'
          //判斷一個值是否是一個函數
          const isFunction = value => value && typeof value === 'function' && value instanceof Function
          //判斷一個值是否是一個Promise
          const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
          //判斷一個值是否是一個對象
          const isObject = value => value && typeof value === 'object' && value instanceof Object
          //執行微任務,沒有返回結果
          function runMicroTask(fn) {
              //首先看微任務隊列函數是否存在,如果存在則使用微任務隊列執行
              if (isFunction(queueMicrotask)) {
                  runMicroTask = f => queueMicrotask(f)
              } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js環境
                  runMicroTask = f => process.nextTick(f)
              } else if (isFunction(MutationObserver)) { //如果是瀏覽器環境
                  runMicroTask = f => {
                      const observer = new MutationObserver(f)
                      const node = document.createTextNode('')
                      observer.observe(node, { characterData: true })
                      node.data = '1' //觸發MutationObserver
                  }
              } else { //如果都不存在,那么使用setTimeout(fn, 0)執行
                  runMicroTask = f => setTimeout(f, 0)
              }
              runMicroTask(fn)
          }
      
          class MyPromise {
              constructor(executor) {
                  //表示狀態是否已指定,保證狀態只會被改變一次
                  let specified = false
                  //狀態
                  let state = PENDING
                  //結果或者原因
                  let value = void 0
      
                  //fulfilled狀態的回調函數
                  let onFulfilledCallbacks = []
                  //rejected狀態的回調函數
                  let onRejectedCallbacks = []
      
                  //如果想看promise運行的狀態和結果,可以使用下面的代碼
                  Object.defineProperty(this, 'state', { get() { return state }, configurable: false, enumerable: false })
                  Object.defineProperty(this, 'value', { get() { return value }, configurable: false, enumerable: false })
      
                  const runOrQueueTasks = (callbacks, requireState, callback) => {
                      //如果callback是函數,那么將其添加到callbacks數組中
                      callback && callbacks.push(callback)
                      //如果是指定狀態,那么使用微任務執行
                      if (state === requireState) {
                          while (callbacks.length) {
                              const cb = callbacks.shift()
                              runMicroTask(() => cb(value)) // 使用微任務執行
                          }
                      }
                  }
      
                  //resolve函數,改變狀態為fulfilled
                  const resolve = (result) => {
                      //當且僅當狀態是pending且未指定時進入
                      if (state === PENDING && !specified) {
                          //如果傳入的是當前Promise對象,那么直接reject
                          if (result === this) {
                              return reject(new TypeError('Chaining cycle detected for promise'))
                          }
                          specified = true;
      
                          //如果result是Thenable,那么調用(ES6白皮書)
                          //如果result是一個Promise,那么吸收它的狀態
                          try {
                              if (result && isFunction(result.then)) {
                                  return runMicroTask(() => {
                                      try {
                                          const res = r => (specified = false, resolve(r)) //臨時打開
                                          const rej = r => (specified = false, reject(r))  //臨時打開                            
                                          result.then(res, rej)
                                      } catch (error) {
                                          reject(error)
                                      }
                                  })
                              }
                          } catch (error) {
                              return reject(error) //如果result.then拋出異常,那么直接reject
                          }
      
                          [state, value] = [FULFILLED, result]
      
                          //fulfilled狀態的回調函數,將其添加到onFulfilledCallbacks數組中,判斷是否執行回調函數
                          runOrQueueTasks(onFulfilledCallbacks, FULFILLED)
                      }
                  }
                  //reject函數,改變狀態為rejected
                  const reject = (reason) => {
                      //當且僅當狀態是pending且未指定時進入
                      if (state === PENDING && !specified) {
                          [state, value, specified] = [REJECTED, reason, true]
      
                          //rejected狀態的回調函數,將其添加到onRejectedCallbacks數組中,判斷是否執行回調函數
                          runOrQueueTasks(onRejectedCallbacks, REJECTED)
                      }
                  }
      
                  //Promise狀態處理過程
                  const promiseResolutionProcedure = (promise, x, resolve, reject) => {
                      // promise和x不能引用同一個對象
                      if (promise === x) {
                          throw new TypeError('Chaining cycle detected for promise')
                      }
      
                      //如果x是一個Promise,那么promise對象直接吸收x的狀態
                      if (isPromise(x)) { //這里兼容一下原生Promise
                          //這里ES6白皮書是放到微隊列中執行的(PromiseA+規范沒有確定)
                          return runMicroTask(() => x.then(resolve, reject))
                      }
      
                      //如果x是對象或者函數
                      if (isObject(x) || isFunction(x)) {
                          let ignoreCall = false
                          try {
                              //取then方法報錯,那么直接reject
                              let then = x.then
                              //如果then是一個函數,那么調用then方法
                              if (isFunction(then)) {
                                  //調用采用x作為this,并傳入兩個參數resolve和reject,并要求resolve和reject只能調用一次 
                                  return runMicroTask(() => then.call(x, y => {
                                      ignoreCall = ignoreCall || !promiseResolutionProcedure(promise, y, resolve, reject)
                                  }, r => {
                                      ignoreCall = ignoreCall || !reject(r)
                                  }))
                              }
                          } catch (error) {
                              //如果then方法已經調用了resolve或reject,那么直接忽略
                              ignoreCall || reject(error)
                          }
                      }
                      //如果x不是一個對象或者函數,那么直接resolve
                      resolve(x)
                  }
      
                  //then方法
                  this.then = (onFulfilled, onRejected) => {
                      const promise = new (this.constructor[Symbol.species] || MyPromise)((resolve, reject) => {
                          //如果onFulfilled是函數則調用
                          state !== REJECTED && runOrQueueTasks(onFulfilledCallbacks, FULFILLED, isFunction(onFulfilled) ? value => {
                              try {
                                  const x = onFulfilled(value)
                                  //根據函數返回結果進行Promise Resolution Procedure過程
                                  promiseResolutionProcedure(promise, x, resolve, reject)
                              } catch (error) {
                                  reject(error)
                              }
                          } : resolve)//否則根據當前狀態直接resolve
      
                          //如果onRejected是函數則調用
                          state !== FULFILLED && runOrQueueTasks(onRejectedCallbacks, REJECTED, isFunction(onRejected) ? value => {
                              try {
                                  const x = onRejected(value)
                                  //根據函數返回結果進行Promise Resolution Procedure過程
                                  promiseResolutionProcedure(promise, x, resolve, reject)
                              } catch (error) {
                                  reject(error)
                              }
                          } : reject)//否則根據當前狀態直接reject
                      })
                      return promise
                  }
      
                  try {
                      executor(resolve, reject)
                  } catch (error) {
                      reject(error) //如果executor拋出異常,那么直接reject
                  }
              }
      
              //以下是ES6白皮書的拓展,不是Promise A+規范的內容
              catch(onRejected) {
                  return this.then(null, onRejected)
              }
              finally(onFinally) {
                  //onFinally是一個不接收任何參數的函數
                  //如果 onFinally 拋出錯誤或返回被拒絕的 promise,則新的 promise 將使用該值進行拒絕
                  const onThen = isFunction(onFinally) ? () => {
                      const result = onFinally()
                      if (isPromise(result)) {
                          return result.then(() => this, () => result)
                      }
                      return this;
                  } : onFinally
                  return this.then(onThen, onThen)
              }
              static resolve(value) {
                  //如果value是一個Promise,那么直接返回
                  if (isPromise(value)) {
                      return value
                  }
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, resolve } = MyPromise.withResolvers.call(this)
                  resolve(value) //直接resolve
                  return promise
              }
              static reject(reason) {
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, reject } = MyPromise.withResolvers.call(this)
                  reject(reason) //直接reject
                  return promise
              }
              static all(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  const results = []
                  //如果是空數組,那么直接返回一個resolved的Promise
                  if (!promises.length) {
                      resolve(results)
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(value => {
                              results[i] = value
                              promises.pop() //每執行完成就彈出一個進行計數
                              //如果全部已經是fulfilled狀態,那么resolve結果
                              promises.length || resolve(results)
                          }, reject)
                      })
                  }
                  return promise
              }
              static race(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  //只要有一個是fulfilled或者rejected,那么當前Promise就需要改變狀態
                  promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))
                  return promise
              }
              static allSettled(promises) {
                  promises = [...promises]
                  const { promise, resolve } = MyPromise.withResolvers()
                  const results = []
                  //如果是空數組,那么直接返回一個resolved的Promise
                  if (!promises.length) {
                      resolve(results)
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(value => {
                              results[i] = { status: FULFILLED, value }
                              promises.pop() //每執行完成就彈出一個進行計數
                              //全部Promise已經是fulfilled或者rejected狀態了,那么resolve
                              promises.length || resolve(results)
                          }, reason => {
                              results[i] = { status: REJECTED, reason }
                              promises.pop() //每執行完成就彈出一個進行計數
                              //全部Promise已經是fulfilled或者rejected狀態了,那么resolve
                              promises.length || resolve(results)
                          })
                      })
                  }
                  return promise
              }
              static any(promises) {
                  promises = [...promises]
                  const { promise, resolve, reject } = MyPromise.withResolvers()
                  const errors = []
                  //如果是空數組,那么直接返回一個rejected的Promise
                  if (!promises.length) {
                      reject(new AggregateError(errors, 'All promises were rejected'))
                  } else {
                      promises.forEach((p, i) => {
                          MyPromise.resolve(p).then(resolve, reason => {
                              errors[i] = reason
                              promises.pop() //每執行完成就彈出一個進行計數
                              //如果有rejected,那么收集所有rejected并最后全局reject
                              promises.length || reject(new AggregateError(errors, 'All promises were rejected'))
                          })
                      })
                  }
                  return promise
              }
              static try(fn, ...args) {
                  //使用call(this)用以支持非Promise構造器(ES6白皮書)
                  const { promise, resolve, reject } = MyPromise.withResolvers.call(this)
                  try {
                      const result = fn(...args)
                      resolve(result)
                  } catch (error) {
                      reject(error)
                  }
                  return promise
              }
              static withResolvers() {
                  let resolve, reject
                  const promise = new this((res, rej) => {
                      resolve = res
                      reject = rej
                  })
                  return { promise, resolve, reject }
              }
      
              static get [Symbol.species]() {
                  return MyPromise
              }
              [Symbol.toStringTag]() {
                  return "MyPromise"
              }
          }

      ??驗證

       ??我們主要在瀏覽器環境下驗證,我們可以嘗試幾個例子,把Promise換成我們自定義的MyPromise,結果是一樣的:

      ??例子一

          Promise.resolve()
              .then(() => {
                  console.log(0)
                  return Promise.resolve(4)
              })
              .then(res => {
                  console.log(res)
              })
          Promise.resolve()
              .then(() => {
                  console.log(1);
              })
              .then(() => {
                  console.log(2);
              })
              .then(() => {
                  console.log(3);
              })
              .then(() => {
                  console.log(5);
              })
              .then(() => {
                  console.log(6);
              })

      ??例子二

          new Promise(function(resolve, reject) {
            console.log(1);
            resolve();
            console.log(2);
          }).then(function() {
            console.log(4);
          });
          setTimeout(()=>console.log(5))
          console.log(3);

      ??例子三

          const first = () => (new Promise((resolve, reject) => {
              console.log(1);
              let p = new Promise((resolve, reject) => {
                  console.log(2);
                  setTimeout(() => {
                      console.log(6);
                      resolve(7);
                  }, 0)
                  resolve(4);
              })
              resolve(5);
              p.then((arg) => {
                  console.log(arg);
              });
      
          }));
      
          first().then((arg) => {
              console.log(arg);
          });
          console.log(3);

      ??總結

      ??以上實現是個人總結,模擬Promise的實現過程,基于ES6的實現,如果有什么錯誤,歡迎指出!

       

      posted @ 2025-07-06 16:56  沒有星星的夏季  閱讀(46)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 图木舒克市| 成人午夜激情在线观看| 亚洲精品一区二区三区蜜| 日本高清中文字幕免费一区二区 | 久久精品波多野结衣| 精品日韩人妻中文字幕| 国产免费久久精品44| 国精品无码一区二区三区在线蜜臀 | 亚洲精品麻豆一二三区| 亚洲高清成人av在线| 国产老头多毛Gay老年男 | 884aa四虎影成人精品| 翘臀少妇被扒开屁股日出水爆乳| 日韩精品理论片一区二区| 那坡县| 日日碰狠狠添天天爽五月婷| 亚洲AV无码久久精品日韩| 亚洲乳大丰满中文字幕| 成人精品老熟妇一区二区| 久久99精品国产麻豆婷婷| 成在人线av无码免费看网站直播| 乐都县| 日韩国产中文字幕精品| 亚洲日产韩国一二三四区| 国产亚洲精品在天天在线麻豆| 99中文字幕国产精品| 国产成人午夜福利院| 婷婷久久香蕉五月综合加勒比| 日韩av一区二区三区不卡| 久久精品伊人狠狠大香网| 乱码中文字幕| 国产精品成人无码久久久| 亚洲一区二区三区十八禁| 日韩中文字幕国产精品| 国产又黄又湿又刺激网站| 天堂…中文在线最新版在线| 一本色道久久加勒比综合| 国产精品女同性一区二区| 九九热精品在线观看| 东方四虎av在线观看| 干老熟女干老穴干老女人|