• 根据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
  • 相关阅读:
    Java学习笔记1---JVM、JRE、JDK
    Java学习笔记2---设置环境变量JAVA_HOME,CLASSPATH,PATH
    第一次博客作业
    2018-2019-2 《Java程序设计》第5周学习总结
    作业四——文法和语言总结与梳理
    作业三——语法书、短语、直接短语、句柄
    作业二——文法和语言
    团队项目-需求分析报告
    团队项目-选题报告
    第一次结对编程作业
  • 原文地址:https://www.cnblogs.com/lyraLee/p/12099493.html
Copyright © 2020-2023  润新知