码迷,mamicode.com
首页 > 其他好文 > 详细

根据PromiseA+规范实现Promise

时间:2019-12-25 23:35:55      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:cycle   err   异常   eof   res   添加   ext   sts   exe   

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

标签:cycle   err   异常   eof   res   添加   ext   sts   exe   

原文地址:https://www.cnblogs.com/lyraLee/p/12099493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!