根据PromiseA+规范实现Promise

Posted lyralee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了根据PromiseA+规范实现Promise相关的知识,希望对你有一定的参考价值。

promiseA+规范测试

1. Promise源码

resolvePromise函数

function resolvePromise(promise, x, resolve, reject) {
  if(x === promise) {
    return reject(new TypeError(`Chaining cycle detected for promise #<Promise>`));
  }
  /**
   * 判断是否是promise有三个条件
   * 1.是对象,且不是null
   * 2.是函数
   * 3.满足1,2其中一个的基础上,有then属性,且是个函数
   */
  if((typeof x === ‘object‘ && x !== null) || typeof x === ‘function‘) {
    // 确保即使x是他人自定义的promise对象时,状态改变也只执行一次
    let called; 
    try { // 如果then属性通过getter定义
      let then = x.then;
      if (typeof then === ‘function‘) {// 是promise
        // then方法调用时绑定this,否则可能会导致this指向变更; 第二个参数成功回调
        then.call(x, y => {
          if(called) return;
          called = true;
          // y仍然可能是promise
          resolvePromise(promise, y, resolve, reject);
        }, r => {//失败回调
          if(called) return;
          called = true;
          reject(r);
        })
      } else {
        resolve(x);
      }
    } catch (e) {
      if(called) return;
      called = true;
      reject(e);
    }
  } else { // 普通值
    resolve(x);
  }
}
module.exports = resolvePromise;

Promise源码

/**
 * 1. Promise实例化时有个执行器函数,会立即执行
 * 2. 执行器有两个方法,第一个是resolve, 第二个是reject
 * 3. promise实例有三种状态,pending, fulfilled, rejected
 *    默认是pending, 调用resolve后变为fulfilled; 调用reject后变为rejected
 * 4. 状态不可逆, 只能pending->fulfilled, 或者pending -> rejected
 * 5. 每个promise实例都有个then方法,then方法有两个参数,
 *    第一个是成功回调onFulfilled,第二个是失败回调onRejected
 * 6. 执行器的resolve函数会触发成功回调onFulfilled,
 *    执行器的reject函数或者throw触发失败回调onRejected
 * 7. then方法返回的是一个promise对象。
 * 
 */
const PENDING = ‘PENDING‘;
const FULFILLED = ‘FULFILLED‘;
const REJECTED = ‘REJECTED‘;
const resolvePromise = require(‘./resolvePromise‘);

class Promise {
  constructor(executor) {
    this.value;
    this.reason;
    this.status = PENDING;
    this.onResolvedCallbacks=[]; // then成功回调队列
    this.onRejectedCallbacks=[]; // then失败回调队列
    let resolve = (value) => {
      if(this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.onResolvedCallbacks.forEach(fn => fn());        
      }
    }
    let reject = (reason) => {
      if(this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;    
        this.onRejectedCallbacks.forEach(fn => fn())    
      }
    }
    try{
      executor(resolve, reject);      
    } catch(err) {
      reject(err)
    }
  }
  
  then(onFulfilled, onRejected) {// 两个回调函数,都是可选参数
    // 当参数不是回调函数或者省略时,赋予默认回调函数,将值向后传递
    onFulfilled = typeof onFulfilled === ‘function‘ ? onFulfilled : val => val;
    onRejected = typeof onRejected === ‘function‘ ? onRejected : e => {throw e};
    // 返回promise可以实现链式调用
    const promise = new Promise((resolve, reject) => {
      if(this.status === FULFILLED) {
        //微任务,等到new实例完成之后,获取返回的promise;否则promise未定义
        process.nextTick(() => { 
          try {
            let x = onFulfilled(this.value);
            // x有可能是promise对象,则需要继续处理,直至返回的是普通数据(非异常和promise)     
            resolvePromise(promise, x, resolve, reject);
          } catch (e) {
            reject(e);
          }          
        })
      }
      if(this.status === REJECTED) {
        process.nextTick(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise, x, resolve, reject);        
          } catch (e) {
            reject(e)
          }          
        })
      }
      if(this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          process.nextTick(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise, x, resolve, reject);
            } catch (e) {
              reject(e);
            }             
          }) 
        })
        this.onRejectedCallbacks.push(() => {
          process.nextTick(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise, x, resolve, reject);
            } catch(e) {
              reject(e);
            }               
          })
        })
      }      
    })
    return promise;
  }
}
module.exports = Promise;

2. 测试是否符合规范

1.全局安装测试命令工具

npm install promises-aplus-tests -g

2. 在代码中添加

// 测试Promise是否符合规范
Promise.deferred = function() {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd;
}

3. 使用命令工具测试

promises-aplus-tests promise.js

 

以上是关于根据PromiseA+规范实现Promise的主要内容,如果未能解决你的问题,请参考以下文章

实现一个符合promiseA+规范的promise

实现一个符合promiseA+规范的promise

Promise的源码实现(完美符合Promise/A+规范)

Promise的源码实现(完美符合Promise/A+规范)

手写Promise A+ 规范

一步一步实现一个Promise A+规范的 Promise