小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

簡單版 Promise/A+,通過官方872個(gè)測試用例

 頭號(hào)碼甲 2021-09-17

promise 標(biāo)準(zhǔn)

在實(shí)現(xiàn) Promise 之前要清楚的是 JavaScript 中的 Promise 遵循了 Promises/A+ 規(guī)范,所以我們在編寫 Promise 時(shí)也應(yīng)當(dāng)遵循這個(gè)規(guī)范,建議認(rèn)真、仔細(xì)讀幾遍這個(gè)規(guī)范。最好是理解事件循環(huán),這樣對(duì)于理解js中的異步是怎么回事非常重要。

https:///

基本使用

 Promise( (resolve, reject) {...}  Promise((resolve, reject)=>'url'=>=>=>}).then(value =>((err)=>})

promise 是處理異步結(jié)果的一個(gè)對(duì)象,承若狀態(tài)改變時(shí)調(diào)用對(duì)應(yīng)的回調(diào)函數(shù),resolve、reject用來改變promise 的狀態(tài),then 綁定成功、失敗的回調(diào)。

環(huán)境準(zhǔn)備

安裝測試工具以及nodemon因?yàn)槲覀円趎ode環(huán)境調(diào)試自己寫的promise

// nodemonnpm install nodemon -D// promise 測試工具npm install promises-aplus-tests -D

增加腳本命令

"testPromise": "promises-aplus-tests myPromise/promise3.js", "dev": "nodemon ./myPromise/index.js -i "

各自的路徑改成自己的即可,這個(gè)在后面會(huì)用來測試。

基本架子

根據(jù)規(guī)范實(shí)現(xiàn)一個(gè)簡單的promise,功能如下

  1. promise的三種狀態(tài)(PENDING、FULFILLED、REJECTED)

  2. 狀態(tài)只能由 Pending 變?yōu)?Fulfilled 或由 Pending 變?yōu)?Rejected ,且狀態(tài)改變之后不會(huì)在發(fā)生變化,會(huì)一直保持這個(gè)狀態(tài)

  3. 綁定then的回調(diào)

  4. 返回成功、失敗的值

  5. 一個(gè)promise 支持調(diào)用多次then

  6. 支持捕獲異常

= 'PENDING'= 'FULFILLED'= 'REJECTED'.status =.value =.reason =.onResolveCallbacks =.onRejectedCallbacks == (value) => (.status ===.status =.value =
        .onResolveCallbacks.forEach(fn =>= (reason) => (.status ===.status =.reason =
        .onRejectedCallbacks.forEach(fn => (.status =
      .onResolveCallbacks.push(() =>.onRejectedCallbacks.push(() => (.status === (.status ==== myPromise

訂閱

   傳進(jìn)來的fn是一個(gè)執(zhí)行器,接受resolve、reject參數(shù),通常我們在構(gòu)造函數(shù)中需要調(diào)用某個(gè)接口,這是一個(gè)異步的操作,執(zhí)行完構(gòu)造函數(shù)之后,在執(zhí)行then(),這個(gè)時(shí)候的狀態(tài)還是pending,所以我們需要把then 綁定的回調(diào)存起來,也可以理解為promise對(duì)象訂閱了這個(gè)回調(diào)。

發(fā)布

   在 resolve,reject函數(shù)中中我們改變了promise 對(duì)象的狀態(tài),既然狀態(tài)改變了,那么我們需要執(zhí)行之前訂閱的回調(diào),所以在不同的狀態(tài)下執(zhí)行對(duì)應(yīng)的回調(diào)即可。

流程

如上所示,實(shí)例化對(duì)象,執(zhí)行構(gòu)造函數(shù),碰到異步,掛起,然后執(zhí)行then()方法,綁定了resolve、reject的回調(diào)。如果異步有了結(jié)果執(zhí)行對(duì)應(yīng)的業(yè)務(wù)邏輯,調(diào)用resolve、或者reject,改變對(duì)應(yīng)的狀態(tài),觸發(fā)我們綁定的回調(diào)。

以上就是最基本的promise架子,但是還有promise 調(diào)用鏈沒有處理,下面繼續(xù)完善...

完善promise 調(diào)用鏈

promose 的精妙的地方就是這個(gè)調(diào)用鏈,首先then 函數(shù)會(huì)返回一個(gè)新的promise 對(duì)象,并且每一個(gè)promise 對(duì)象又有一個(gè)then 函數(shù)。驚不驚喜原理就是那么簡單,回顧下then的一些特點(diǎn)

then 特點(diǎn)

  1. then 返回一個(gè)新的promise 對(duì)象

  2. then 綁定的回調(diào)函數(shù)在異步隊(duì)列中執(zhí)行(evnet loop 事件循環(huán))

  3. 通過return 來傳遞結(jié)果,跟fn一樣如果沒有return,默認(rèn)會(huì)是 underfined

  4. 拋出異常執(zhí)行綁定的失敗函數(shù)(最近的promise),如果沒有,則執(zhí)行catch

  5. then中不管是不是異步只要resolve、rejected 就會(huì)執(zhí)行對(duì)應(yīng) onFulfilled、onRejected 函數(shù)

  6. then中返回promise狀態(tài)跟執(zhí)行回調(diào)的結(jié)果有關(guān),如果沒有異常則是FULFILLED,就算沒有retun 也是FULFILLED,值是underfined,有異常就是REJECTED,接著走下個(gè)then 綁定的onFulfilled 、onRejected 函數(shù)

   根據(jù)上面的特點(diǎn)以及閱讀規(guī)范我們知道then()函數(shù)主要需要處理以下幾點(diǎn)

  • 返回一個(gè)新的promise

  • 值怎么傳給then返回的那個(gè)promise

  • 狀態(tài)的改變

返回一個(gè)新的promise

因?yàn)閜romise 的鏈?zhǔn)秸{(diào)用涉及到狀態(tài),所以then 中返回的promise 是一個(gè)新的promise

then(onFulfilled, onRejected) {
   let promise2 = new Promise((resolve, reject) => {     // do ...   })   return promise2
 }

值的傳遞、狀態(tài)的改變

let p = new myPromise((resolve, rejected) => {  // do ...})
p.then(
  value => {    return 1
  },
  reason => {}
  )
  .then(
    value => {      return new Promise((resolve, rejected) => {
        resolve('joel')
      })
    },
    reason => {}
    )
  .then(
    value => {      throw 'err: 出錯(cuò)啦'
    },
    reason => {}
    )

then 返回的值可能是一個(gè)普通值、promise對(duì)象、function、error 等對(duì)于這部分規(guī)范文檔也有詳細(xì)的說明

image.png

[[Resolve]](promise, x)

這個(gè)可以理解為promise 處理的過程,其中x是執(zhí)行回調(diào)的一個(gè)值,promise 是返回新的promise對(duì)象,完整代碼如下

我們將這部分邏輯抽成一個(gè)獨(dú)立的函數(shù) 如下

// 處理then返回結(jié)果的流程function resolvePromise(promise2, x, resolve, reject) {  if (promise2 === x) {    return reject(new TypeError('Chaining cycle detected for promise #<myPromise>'))
  }

  let called = false

  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {    try {
      let then = x.then      // 判斷是否是promise
      if (typeof then === 'function') {
        then.call(x, (y) => {          // 如果 resolvePromise 以值 y 為參數(shù)被調(diào)用,則運(yùn)行 [[Resolve]](promise, y)
          if (called) return
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, (r) => {          if (called) return
          called = true
          reject(r)
        })
      } else {
        resolve(x)
      }
    } catch (e) {      if (called) return
      called = true
      reject(e)
    }
  } else {    // 如果 x 不為對(duì)象或者函數(shù),以 x 普通值執(zhí)行回調(diào)    resolve(x)
  }
}

測試

promises-aplus-tests 這個(gè)工具我們必須實(shí)現(xiàn)一個(gè)靜態(tài)方法deferred,官方對(duì)這個(gè)方法的定義如下:

deferred: 返回一個(gè)包含{ promise, resolve, reject }的對(duì)象

promise 是一個(gè)處于pending狀態(tài)的promise

resolve(value) 用value解決上面那個(gè)promise

reject(reason) 用reason拒絕上面那個(gè)promise

添加如下代碼

myPromise.defer = myPromise.deferred = function () {
  let deferred = {}

  deferred.promise = new myPromise((resolve, reject) => {
    deferred.resolve = resolve
    deferred.reject = reject
  })  return deferred
}

在編輯執(zhí)行我們前面加的命令即可

npm run testMyPromise

image.png

 

完善其他方法

  1. all

  2. allSettled

  3. any

  4. race

  5. catch

  6. finlly

npm run dev // 可以用來測試這些方法

image.png

源碼

源碼

比較官方的源碼: https://github.com/then/promise 

參考

https:///

https://www.jianshu.com/p/4d266538f364

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多