手写promise

76 阅读1分钟

一、简单版本(干货)

1、未处理什么类型错误

 function myPromise(executor) {
      this.state = 'pending';
      this.result = '';
      this.fullfiledArr = [];
      this.rejectedArr = [];
      var change;
      //注意这里要设置this,否则在change函数里面容易出现this丢失的情况
      var self = this
      change = function (state, result) {
          if (self.state !== 'pending') return
          self.state = state;
          self.result = result;
          setTimeout(function () {
              var callArr = self.state == 'resolved' ? self.fullfiledArr : self.rejectedArr,
                  i = 0,
                  len = callArr.length;
              for (;i < len;i++) {
                  callArr[i](self.result)
              }
          })
      }
      try {
          executor(function (result) {
              change('resolved', result)
          }, function (reason) {
              change('rejected', reason)
          })
      } catch (e) {
          change('rejected', e)
      }
  }
  function handle(newPromise, x, resolve, reject) {
      if (x === newPromise) throw new TypeError('Chaining cycle detected for promise #<Promise>');
      if (x instanceof myPromise) {
          x.then(function (result) {
              resolve(result)
          }, function (err) {
              reject(err)
          })
      } else {
          resolve(x)
      }
  }
  myPromise.prototype = {
      constructor: myPromise,
      then: function (onfullfiled, onrejected) {
        if (typeof onfulfilled !== "function") {
            onfulfilled = function onfulfilled(result) {
                return result;
            };
        }
        if (typeof onrejected !== "function") {
            onrejected = function onrejected(reason) {
                throw reason;
            };
        }
          var self = this,
              x,
              newPromise = new myPromise(function (resolve, reject) {
                  if (self.state == 'resolved') {
                      //这里模仿异步微任务
                      setTimeout(function () {
                          try {
                              x = onfullfiled(self.result)
                              handle(newPromise, x, resolve, reject)
                          } catch (e) {
                              reject(e)
                          }
                      })

                  } else if (self.state == 'rejected') {
                      setTimeout(function () {
                          try {
                              x = onrejected(self.result)
                              handle(newPromise, x, resolve, reject)
                          } catch (e) {
                              reject(e)
                          }
                      })
                  } else {
                      self.fullfiledArr.push(function (result) {
                          try {
                              x = onfullfiled(result)
                              handle(newPromise, x, resolve, reject)
                          } catch (e) {
                              reject(e)
                          }
                      })
                      self.rejectedArr.push(function (reason) {
                          try {
                              x = onrejected(reason)
                              handle(newPromise, x, resolve, reject)
                          } catch (e) {
                              reject(e)
                          }
                      })
                  }
              })
          return newPromise
      },
      catch: function (onrejected) {
        return this.then(null, onrejected)
    }
  }

2、实现Promise的all、resolve、reject方法

 myPromise.resolve = function (result) {
      return new myPromise(function (resolve) {
          resolve(result)
      })
  }
  myPromise.reject = function (reason) {
      return new myPromise(function (resolve, reject) {
          reject(reason)
      })
  }
  myPromise.all = function (promiseArr) {
      return new myPromise(function (resolve, reject) {
          var i = 0,
              len = promiseArr.length,
              item,
              resultArr = [];
          for (;i < len;i++) {
              item = promiseArr[i]
              if (!(promiseArr[i] instanceof myPromise)) {
                  promiseArr[i] = myPromise.resolve(promiseArr[i])
              }
              (function (i) {
                  promiseArr[i].then(function (result) {
                      resultArr[i] = result
                      if (i == len) resolve(resultArr)
                  }, function (reason) {
                      reject(reason)
                  })
              })(i)
          }
      })
  }

3、实现promise的race方法

myPromise.race = function (promiseArr) {
    return new myPromise(function (resolve, reject) {
        var i = 0,
            len = promiseArr.length,
            item
        for (;i < len;i++) {
            item = promiseArr[i]
            if (!(item instanceof myPromise)) {
                item = myPromise.resolve(item)
            }
            item.then(function (result) {
                resolve(result)
            }, function (result) {
                reject(result)
            })
        }
    })
}