Promise/A+规范+ECMAScript6的Promsie的扩展api源码实现

什么是Promise?

MDN文档对Promise的解释是: Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
民间也有一种说法是: Promise是优雅解决异步回调函数嵌套地狱问题的一种解决方案。

下面是我个人对Promise的一个通俗的解释:
在这里插入图片描述

什么是Promise/A+? 它跟ECMAScript 6的Promise又是什么关系?

  • Promise/A+是Promise的一个开放的标准或者是规范,它规范了Promise的术语和要求(包括Promise的三种状态、必须提供一个then方法和Promise的解决流程)。
  • ECMAScript 6里面的Promise是Promise/A+规范的一种实现方案。它是一个规范的具体的一种实现方案,它在原有的Promise/A+规定上扩展了一些API:

Promise.prototype.catch()
Promise.prototype.finally()
Promise.allSettled()
Promise.all()
Promise.race()
Promise.any()
Promise.reject()
Promise.resolve()

下面是用图来形容它们之间的关系

在这里插入图片描述


来看看Promise流程图:

image

下面是一个实现了Promsoe/A+规范同时也扩展了ECMAScript6的PromiseAPI的源码并且含有大量注释。(通过了所有promises-aplus-test的测试案例)

promises-aplus-test

如果你也想测试你自己编写的Promsie是否符合**Promise/A+**规范可以下载一个 “promises-aplus-test” 的工具来测试。下面是安装命令:

	npm install promises-aplus-tests -g

下面是promises-aplus-test的用法:

  Promise.deferred = function() {
   
    const deferred = {
   }
    deferred.promise = new Promise((resolve, reject) => {
   
        deferred.resolve = resolve
        deferred.reject = reject
    })
    return deferred
  }
  module.exports = Promise;

在你编写的promise文件的末尾添加这些代码然后在命令行运行下面命令就可以

	promises-aplus-tests 你要测试的文件名.js
下面是我编写的Promise源码
const PEDDING = "pending",
    FULFILLED = "fulfilled",
    REJECTED = "rejected";
function isPromise(val) {
   
    return (
        val !== undefined &&
        val !== null &&
        (typeof val === 'object' || typeof val === 'function') &&
        typeof val.then === 'function'
    );
}
/**
 * @todo  The Promise Resolution Procedure=>Promise的解决流程
 * @description Promise/A+ 规范
 *  的承诺解决过程是一个抽象的操作作为输入一个承诺和一个值,它表示我们作为[[Resolve]](promise, x)。如果x是可能的,则在行为至少类似于承诺的假设下,
 *  尝试promise采用的状态。否则,它将满足value 。xxpromisex只要对约定的实现公开Promises / A +兼容的then方法,对约定的实现就可以进行互操作。
 *  它还允许Promises / A +实现以合理的then方法“同化”不合格的实现。
    要运行[[Resolve]](promise, x),请执行以下步骤:
    2.3.1    如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
    2.3.2    如果x是一个承诺,则采用其状态[ 3.4 ]:
      2.3.2.1      如果x未决,则promise必须保持未决状态,直到x实现或被拒绝。
      2.3.2.2      如果/何时x满足,promise则以相同的值满足。
      2.3.2.3      如果/何时x被拒绝,promise则以相同的理由拒绝。
    2.3.3    否则,如果x是对象或函数,
      2.3.3.1     我们then是x.then。[ 3.5 ]
      2.3.3.2     如果检索属性x.then中抛出的异常的结果e,拒绝promise与e作为的原因。
      2.3.3.3     如果then是函数,请使用xas this,第一个参数resolvePromise和第二个参数进行调用rejectPromise,其中:
        2.3.3.3.1      如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
        2.3.3.3.2      如果/当rejectPromise是带一个理由r,拒绝promise与r。
        2.3.3.3.3      如果同时调用resolvePromise和rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,而所有其他调用均被忽略。
        2.3.3.3.4      如果调用then引发异常e,
        2.3.3..3.4.1       如果resolvePromise或rejectPromise已经被调用,则忽略它。
        2.3.3..3.4.2       否则,拒绝promise与e作为的原因。
      2.3.3.4          如果then不是一个函数,实现promise用x。
    2.3.4     如果x不是一个对象或功能,实现promise与x。
        如果使用参与循环的可循环链的可转换组件来解决承诺,从而[[Resolve]](promise, thenable)最终导致递归性质[[Resolve]](promise, thenable)被再次调用,
    则遵循上述算法将导致无限递归。鼓励但不是必需的实现,以检测这种递归并promise以提供信息TypeError为理由的拒绝。[ 3.6 ]
 * @param {Promise} promise2 
 * @param {*} x 
 * @param {Function} resolve 
 * @param {Function} reject 
 * @returns {void}
 */
function resolvePromise(promise2, x, resolve, reject) {
   
    //如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
    /**
     * 例子:
     * const p=new Promise((resolve,reject)=>{
     *  resolve(xxx);
     * }).then(v=>{
     *  return p;
     * })
     */
    if (promise2 === x) {
   
        return reject(new TypeError('Chaining cycle detected for promise'));
    }
    //保证promise2的onFulfilled或者onRejected只被调用一次 防止多次调用
    //比如:
    /**
     * new Promise((resolve,reject)=>{
     *    resolve(xxx);
     *    reject(xxx);
     *    resolve(xxx);
     *  });
     * 这样就会导致promise2的onFulfilled或者onRejected被多次调用
     */
    let called = false;
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
   
        try {
   
            //then be x.then=>取出then
            const then = x.then;
            // 如果then是函数,就默认是promise了
            if (typeof then === 'function') {
   
                then.call(x,
                    //If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).=> 如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
                    (y) => {
   
                        //只能调用一次
                        if (called) return;
                        called = true;
                        //如果y依旧是一个promise 那么就递归解析
                        /**
                         * 例子:
                         * new Promose((resolve,reject)=>{
                         *     resolve('xxx');
                         * }).then((v)=>{
                         *    return new Promise((resolve,reject)=>{
                         *      setTimeout(()=>{
                         *         resolve(new Promise((resolve,reject)=>{
                         *              resolve(new Promise((resolve,reject)=>{
                         *                  resolve(new Promise(...);//嵌套地狱
                         *              }))
                         *          }))
                         *      }13000)
                         *  })
                         * })
                         */
                        resolvePromise(promise2, y, resolve, reject);
                    },
                    //If/when rejectPromise is called with a reason r, reject promise with r.=>  如果/当rejectPromise是带一个理由r,拒绝promise与r。
                    (r) => {
   
                        //只能调用一次
                        if (called) return;
                        called = true;
                        reject(r);
                    });
            } else {
   
                resolve(x);
            }
        } catch (e) {
   
            //取then失败或者流程报错走到这里
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
   
        //If x is not an object or function, fulfill promise with x.=>如果x不是一个对象或者函数 
        resolve(x);
    }
}
class Promise {
   
    /**
     * @description Promise 构造器主要用于包装不支持promise(返回值不是Promise)的函数。
     * @param {*} executor 
     */
    constructor(executor) {
   
        if (isPromise
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值