根据PromiseA+规范实现Promise

promiseA+规范测试

1. Promise源码

isPromise函数

function isPromise(value) {
  if((typeof value === 'object' && value !== null) || typeof value === 'function') {
    return typeof value.then === 'function'
  }
  return false;
}

module.exports = isPromise;

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对象。
 * 8. 每个promise对象都有catch方法。
 * 9. Promise类(构造函数)有静态方法Promise.resolve(value)/Promise.reject(value)
 * 10. Promise类(构造函数)有静态方法Promise.all([...])返回一个promise实例
 *     解决异步任务并发的问题,返回结果数组按照异步任务的顺序返回
 */
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
const resolvePromise = require('./resolvePromise');
const isPromise = require('./isPromise');

class Promise {
  constructor(executor) {
    this.value;
    this.reason;
    this.status = PENDING;
    this.onResolvedCallbacks=[]; // then成功回调队列
    this.onRejectedCallbacks=[]; // then失败回调队列
    let resolve = (value) => {
      // resolve的值如果是promise, 则一直取值直到非promise为止
      if (value instanceof Promise) {
        value.then(resolve, reject);
      } else if(this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        if (this.onResolvedCallbacks.length > 0) {
          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;
  }
  catch(errCallback) {
    return this.then(null, errCallback);
  }
  finally(callback) {
    return this.then((value) => {
      return Promise.resolve(callback()).then(() => value)
    }, (err) => {
      return Promise.resolve(callback()).then(() => {throw err})
    })
  }
}
Promise.resolve = (value) => {
  if(isPromise(value)) {
    return value;
  }
  return new Promise((res,rej) => {
    res(value);
  })
}
Promise.reject = (reason) => {
  if(isPromise(reason)) {
    return reason;
  }
  return new Promise((resolve,reject) => {
    reject(reason);
  })
}
Promise.all = ( promises) => { // 处理并发;promises的数组中可以不是promise
  return new Promise((resolve,reject) => {
    let arr = [];// 存储promise的结果
    let index = 0; //确保每个promise项都执行过
    let processData = (i, data) => {
      arr[i] = data;
      if (++index === promises.length) {
        resolve(arr);
      }
    }
    for(let i=0; i<promises.length; i++) {
      let current = promises[i];
      if(isPromise(current)) {
        current.then((data) => {
          processData(i, data);
        }, reject); //只要有一个reject状态就变rejected
      } else {
        processData(i, current);
      }
    }
  })
}
Promise.race = (promises) => {
  return new Promise((resolve, reject) => {
    for(let i=0; i< promises.length; i++) {
      let current = promises[i];
      if(isPromise(current)) {
        current.then(resolve, reject)
      } else {
        resolve(current);
      }
    }
  })
}
// 测试Promise是否符合规范
Promise.deferred = function() {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd;
}
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
原文地址:https://www.cnblogs.com/lyraLee/p/12099493.html