欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript手寫(xiě)Promise核心原理

 更新時(shí)間:2022年06月24日 11:39:05   作者:??遠(yuǎn)方的小草????  
這篇文章主要介紹了JavaScript手寫(xiě)Promise核心原理,promise?可以說(shuō)是出場(chǎng)率很高的api了,這篇文章手寫(xiě)一版promise,可以加強(qiáng)對(duì)promise的認(rèn)識(shí)

準(zhǔn)備

  • 首先,promise 有三種狀態(tài):pending fulfilled rejected;
  • promise在實(shí)例化操作中, 有兩個(gè)改變狀態(tài)的方法,分別為resolve,reject;
  • promise有很多方法,詳情請(qǐng)見(jiàn) mdn, 本篇文章先實(shí)現(xiàn) promise的核心apithencatch;

我們使用 es6 提供的 class 來(lái)實(shí)現(xiàn)

class MyPromise {
 // 準(zhǔn)備三個(gè)狀態(tài)
 static PENDING = 'pending';
 static FULFILLED = 'fulfilled';
 static REJECTED = 'rejected';

 constructor(executor) {
   this.status = MyPromise.PENDING; // 表示promise的狀態(tài)
   this.value = null;  // 表示promise的值
   try {
     executor(this.resolve.bind(this), this.reject.bind(this))
   } catch (error) {
     this.reject(error)
   }
 }
 resolve() {
 }
 reject() {
 }
}

在這里 executor 就是傳遞過(guò)來(lái)的函數(shù),可以接收 resolvereject,這里將內(nèi)部的兩個(gè)方法給傳入,如果在調(diào)用的過(guò)程中報(bào)錯(cuò)了會(huì)調(diào)用reject方法

完善 resolve/reject

他們做的工作分為以下幾部

  • 將狀態(tài)改為pendingfulfilled 或 rejected
  • 可以接受一個(gè)值為當(dāng)前的promisevalue
  resolve(value) {
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.FULFILLED;
      this.value = value
    }
  }
  reject(value) {
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.REJECTED;
      this.value = value
    }
  }

then

then 函數(shù)可以接受兩個(gè)參數(shù),分別為成功的回調(diào)函數(shù)和失敗的回調(diào)函數(shù),并且回調(diào)函數(shù)的默認(rèn)為一個(gè)函數(shù)

  • 狀態(tài)為 fulfilled 執(zhí)行第一個(gè)回調(diào),rejected 執(zhí)行第二個(gè)回調(diào)
  • 回調(diào)函數(shù)中給傳入當(dāng)前的 value
  • then的執(zhí)行為異步的
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    if (typeof onFulfilled !== 'function') {
      onRejected = value => value
    }

    if (this.status === MyPromise.FULFILLED) {
      setTimeout(() => {
        onFulfilled(this.value)
      })
    }

    if (this.status === MyPromise.REJECTED) {
      setTimeout(() => {
        onRejected(this.value)
      })
    }
  }

驗(yàn)證一下:

console.log(1)
new MyPromise((resolve, reject) => {
  console.log(2)
  resolve('成功')
}).then(res => console.log(res))

console.log(3)

// 打印 1 2 3 成功

當(dāng)promise里面有異步代碼的時(shí)候,這個(gè)時(shí)候運(yùn)行到.then方法 狀態(tài)為pending,下來(lái)增加一下異步任務(wù)的處理

異步處理

當(dāng)狀態(tài)為pending的時(shí)候,表示執(zhí)行的是異步任務(wù),這個(gè)時(shí)候我們可以增加一個(gè)callback,把異步執(zhí)行的內(nèi)容添加到這個(gè)callback中,當(dāng)執(zhí)行完異步代碼的時(shí)候,會(huì)執(zhí)行異步函數(shù)的callback的任務(wù)

constructor(executor) {
  // ...
  this.callbacks = []; // 用來(lái)存儲(chǔ)回調(diào)函數(shù)的容器
  // ...
}
resolve(value) {
  // ...
  this.callbacks.forEach(({ onFulfilled }) => onFulfilled(value)) 
  // 當(dāng)執(zhí)行到這里的時(shí)候 如果有onFulfilled 就說(shuō)明已經(jīng)執(zhí)行完then方法給容器添加內(nèi)容了。把resolve的值傳遞給onFulfilled
} 
reject(value) {
  // ...
  this.callbacks.forEach(({ onRejected }) => onRejected(value))
  // 當(dāng)執(zhí)行到這里的時(shí)候 如果有onRejected 就說(shuō)明已經(jīng)執(zhí)行完then方法給容器添加內(nèi)容了。把reject的值傳遞給onFulfilled
}
then(onFulfilled, onRejected) {
  // ...
  if (this.status === MyPromise.PENDING) {
    this.callbacks.push({
      onFulfilled: value => {
        setTimeout(() => {
          onFulfilled(value)
        })
      },
      onRejected: value => {
        setTimeout(() => {
          onRejected(value)
        })
      }
    })
  }
 }

驗(yàn)證一下:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功')
  })
}).then(res => console.log(res)) 

// 打印  成功

then 函數(shù)可以鏈?zhǔn)秸{(diào)用,接下來(lái)我們完善一下

鏈?zhǔn)秸{(diào)用

鏈?zhǔn)秸{(diào)用的核心就是返回一個(gè)新的 promise,當(dāng)成功調(diào)用的時(shí)候調(diào)用新的promiseresolve,失敗reject,并且鏈?zhǔn)秸{(diào)用會(huì)把前一個(gè)的返回值當(dāng)作下一個(gè)的 resolve 的狀態(tài)

then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    if (typeof onFulfilled !== 'function') {
      onRejected = value => value
    }
    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.FULFILLED) {
        setTimeout(() => {
          const result = onFulfilled(this.value)
          resolve(result)
        })
      }

      if (this.status === MyPromise.REJECTED) {
        setTimeout(() => {
          const result = onRejected(this.value)
          resolve(result) 
        })
      }
      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
          onFulfilled: value => {
            setTimeout(() => {
              const result = onFulfilled(value)
              resolve(result)
            })
          },
          onRejected: value => {
            setTimeout(() => {
              const result = onRejected(value)
              resolve(result)
            })
          }
        })
      }
    })
  }

驗(yàn)證一下:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject('失敗')
  })
}).then(res => res, err => err).then(res => console.log(res))

// 打印  失敗

如果.then的回調(diào)函數(shù)返回的是promise的情況也要做個(gè)處理

邊界處理

實(shí)現(xiàn)前:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功')
  })
}).then(
  res => new MyPromise((resolve, reject) => {
    resolve(res)
  }),
  err => err
).then(res => console.log(res))

// 打印  { "status": "fulfilled", "value": "成功", "callbacks": [] }

當(dāng)判斷返回值為 MyPromise 的時(shí)候,需要手動(dòng)調(diào)用 .then 的方法取他的值,并且吧當(dāng)前的 promise 的改變狀態(tài)的函數(shù)透出給 then 方法

  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    if (typeof onFulfilled !== 'function') {
      onRejected = value => value
    }
    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.FULFILLED) {
        setTimeout(() => {
          const result = onFulfilled(this.value)
          if (result instanceof MyPromise) { 
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        })
      }

      if (this.status === MyPromise.REJECTED) {
        setTimeout(() => {
          const result = onRejected(this.value)
          if (result instanceof MyPromise) {
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        })
      }

      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
          onFulfilled: value => {
            setTimeout(() => {
              const result = onFulfilled(value)
               if (result instanceof MyPromise) {
                 result.then(resolve, reject)
               } else {
                resolve(result)
               }
            })
          },
          onRejected: value => {
            setTimeout(() => {
              const result = onRejected(value)
              if (result instanceof MyPromise) {
                result.then(resolve, reject)
              } else {
                resolve(result)
              }
            })
          }
        })
      }
    })
  }

驗(yàn)證:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功')
  })
}).then(
  res => new MyPromise((resolve, reject) => {
    resolve(res)
  }),
  err => err
).then(res => console.log(res))

// 打印  成功

到這里 .then 方法就實(shí)現(xiàn)差不多了,接下來(lái)實(shí)現(xiàn) catch 方法

catch

catch 方法可以處理拒絕的狀態(tài)和錯(cuò)誤的狀態(tài):

  catch(onFulfilled) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.REJECTED) {
        setTimeout(() => {
          const result = onFulfilled(this.value)
          if (result instanceof MyPromise) {
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        })
      }
    })
  }

驗(yàn)證:

new MyPromise((resolve, reject) => {
  reject('失敗')
}).catch(res=> console.log(res))

// 打印  失敗

道理其實(shí)和 then 是相同的,到這里主功能基本上就差不多了,但是有很多重復(fù)的地方,優(yōu)化一下

優(yōu)化后完整代碼

class MyPromise {
  // 準(zhǔn)備三個(gè)狀態(tài)
  static PENDING = 'pending';
  static FULFILLED = 'fulfilled';
  static REJECTED = 'rejected';

  constructor(executor) {
    this.status = MyPromise.PENDING; // 表示promise的狀態(tài)
    this.value = null;  // 表示promise的值
    this.callbacks = [];
    try {
      executor(this.resolve.bind(this), this.reject.bind(this))
    } catch (error) {
      console.log(error)
      this.reject(error)
    }
  }
  resolve(value) {
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.FULFILLED;
      this.value = value
    }
    this.callbacks.forEach(({ onFulfilled }) => onFulfilled(value))
  }
  reject(value) {
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.REJECTED;
      this.value = value
    }
    this.callbacks.forEach(({ onRejected }) => onRejected(value))
  }
  parse({ callback, resolve, reject, value = this.value }) {
    setTimeout(() => {
      const result = callback(value)
      if (result instanceof MyPromise) {
        result.then(resolve, reject)
      } else {
        resolve(result)
      }
    })
  }
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    if (typeof onFulfilled !== 'function') {
      onRejected = value => value
    }
    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.FULFILLED) {
        this.parse({ callback: onFulfilled, resolve, reject })
      }

      if (this.status === MyPromise.REJECTED) {
        this.parse({ callback: onRejected, resolve, reject })
      }

      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
          onFulfilled: value => {
            this.parse({ callback: onFulfilled, resolve, reject, value })
          },
          onRejected: value => {
            this.parse({ callback: onRejected, resolve, reject, value })
          }
        })
      }
    })
  }
  catch(onFulfilled) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = value => value
    }

    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.REJECTED) {
        this.parse({ callback: onFulfilled, resolve, reject })
      }
    })
  }
}

到此這篇關(guān)于JavaScript手寫(xiě)Promise核心原理的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論