手写Promise A+

手写Promise A+

Promise 是异步编程的一种解决方案。ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点:

  • 对象的状态不受外界影响
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

基础实现Promise

function Promise(cb){
    let self = this;
  this.status = 'PENDING';//promise的状态 默认pending
  this.value = null;//promise的值
  this.onResolvedCallback = [];//成功的回调函数
  this.onRejectedCallback = [];//失败的回调函数
  function resolve(value){
          setTimeout(() => {
              self.value = value;
          //promise的状态变为resolved 之后,遍历调用成功回调函数
          self.onResolvedCallback.forEach(cb => {
                cb(self.value)
          })
      })
  }

  function reject(value){
          setTimeout(() => {
              self.value = value;
            //promise的状态变为rejected 之后,遍历调用成功回调函数
          self.onRejectedCallback.forEach(cb => {
                cb(self.value)
          })
      })
  }
}

在上面的代码中,我们建立一个Promise函数,在函数中添加了Promise的返回值value、成功的回调函数队列onResolvedCallback、失败的函数回调队列onRejectedCallback
然后编写了函数的resolvereject方法,在方法中使用setTimeout来实现异步。方法都接受一个参数,表示当Promise状态变为resolved、rejected时返回值。最后,遍历对应的回调队列,触发队列中的每一个回调函数,并且将value传入。

实现then

then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

Promise.prototype.then = function(onResolved,onRejected){
  //避免传入的不是函数
  onFulfilled =
        typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected =
        typeof onRejected === 'function'
            ? onRejected
            : error => {
                    throw error
              }
  //缓存this上下文对象 在哪个promise中调用,指向谁
  let self = this;
    return new Promise((resolve,reject) => {
      if(self.status === 'RESOLVED'){//成功
        self.onResolvedCallback.push(function(){
        //调用成功回调 获取结果
          let result = onResolved(self.value);
        //如果返回值为新的promise对象 则继续调用then
        if(result instanceof Promise){
            result.then(resolve,reject);
        }else {
          //否则直接resolve
            resolve(result)
        }
      })
    }else if(self.status === 'REJECTED'){
        self.onRejectedCallback.push(function(){
        //调用回调 获取结果
          let result = onRejected(self.value);
        //如果返回值为新的promise对象 则继续调用then
        if(result instanceof Promise){
            result.then(resolve,reject);
        }else {
          //否则直接resolve
            reject(result)
        }
      })
    }else if (self.status === 'PENDING') {
            self.onResolvedCallback.push(function() {
                let result = onResolved(self.value)
                if (result instanceof Promise) {
                    result.then(resolve, reject)
                } else {
                    resolve(result)
                }
      })
      self.onRejectedCallback.push(function(){
        let result = onRejected(self.value);
        if(result instanceof Promise){
          result.then(resolve,reject)
        }else {
          reject(result)
        }
            })
        }
  })
}

then函数中,我们需要保存调用then函数时的上下文对象,然后根据此时promise的状态,分别进行不同的处理。

实现all

promise.all(),具有以下特性:

  1. 接收一个 `Promise_` 实例的数组或具有 `Iterator_`_ 接口的对象,_
  2. 如果元素不是 `Promise_` 对象,则使用 `Promise.resolve__ 转成 _Promise_` 对象_
  3. 如果全部成功,状态变为 `resolved_`_,返回值将组成一个数组传给回调
  4. 只要有一个失败,状态就变为 `rejected__,返回值将直接传递给回调__all() `的返回值也是新的 `Promise_` 对象_
Promisre.prototype.all = function(promises){
    return new Promise((resolve,reject) => {
      if(!Array.isArray(promises)){
        return reject(new TypeError('arguments must be an array'))
    }
    let count = 0,
        len=  promises.length,
        resolveValues = new Array(len);
    for (let i = 0; i < len; i++) {
      promises[i].then((value) => {
        count++;
        resolveValues[i] = value;
        if(count === len){
          return resolve(resolveValues)
        }
      },(value) => {
        return reject(value)
      })
    }
  })
}

ok,这样我们的promise A+基本就简单实现了。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!