乐趣区

Promisea规范

promise/a+ 规范概念

Promise/A+ 是 Promise 最小的一个规范,它包括:

1 promise 状态
2 then 方法
3 promise 解析过程

任何能跑通测试的 Promise 实现都被 Promise/A+ 认可。

promise/a+ 出现的原因

1 我们不知道异步请求什么时候返回数据,所以我们就需要些回调函数。但是在某些情况下我们需要知道数据是在什么时候返回的,然后进行一些处理。
2 当我们在异步回调里面处理的操作还是异步操作的时候,这样就形成了异步回调的嵌套

那么我们就按照这个文档来写一个可通过测试的 promise 吧 (https://www.ituring.com.cn/ar… 写之前最好读几遍规范内容。话不多少,上代码,为了更好的展示我给代码打了很多注释,虽然很乱但是挺清楚的

// 规范三种状态,默认是 pending; 定义宏变量是为了书写时方便一点
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function resolvePromise(promise2, x, resolve, reject) {
` 如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise`
    if (promise2 === x) {reject(new TypeError('Chaining cycle detected for promise #<Promise>--'))
    }
    let called;
    ` 判断如果是对象或者函数 `
    if ((typeof x === 'object' && x != null) || typeof  x === 'function') {  
        try {
        ` 文档规定 `
            let then = x.then;
            if (typeof then === 'function') {
            ` 如果 then 是函数,将 x 作为函数的作用域 this 调用之,传递两个回调函数作为参数 `
                then.call(x, y => {
                ` 防止重复调用 `
                    if (called) return;
                    called = true;
                    ` 如果是嵌套的 promise 那么需要递归遍历到普通值为止 `
                    resolvePromise(promise2, y, resolve, reject)
                }, r => {
                 ` 防止重复调用 `
                    if (called) return;
                    called = true;
                    reject(r)
                })
            } else {
          ` 如果 then 不是函数,以 x 为参数执行 promise`
                resolve(x)
            }
        } catch (e) {
         ` 防止重复调用 `
            if (called) return;
            called = true;
            ` 如果取 x.then 的值时抛出错误 e,则以 e 为据因拒绝 promise`
            reject(e)
        }
    } else {
    ` 如果是普通值 `
        resolve(x)
    }
}
` 创建一个 promise 类 `
class Promise {constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
        ` 定义 executor(resolve, reject) 中的 resolve,参数 value`
        let resolve = value => {
        ` 只有状态为 pending 的情况下才能转换状态 `
            if (this.status === PENDING) {
            ` 调用 reslove 函数 状态变为成功态 `
                this.status = FULFILLED;
                ` 定义变量接受传进来的参数 `
                this.value = value;
                ` 遍历成功事件池中的方法并依次执行(解决异步)`
                this.onFulfilledCallbacks.forEach(fn => fn())
            }
        };
      ` 定义 executor(resolve, reject) 中的 reject, 参数 reason`
        let reject = reason => {
       ` 只有状态为 pending 的情况下才能转换状态 `
            if (this.status === PENDING) {
              ` 调用 reject 函数 状态变为失败态 `
                this.status = REJECTED;
                ` 定义变量接受传进来的参数 `
                this.reason = reason;
                ` 遍历失败事件池中的方法并依次执行(解决异步)`
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        };
        try {
         ` 默认传进一个函数 executor,并且执行,promise 中的提供两个函数 `
            executor(resolve, reject)
        } catch (e) {
        ` 如果抛错调用 reject(文档写的)`
            reject(e)
        }

    }

    then(onFulfilled, onRejected) {
    `(成功态)连续调用时如果函数没有写给他附一个默认值继续向下传递 `
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : d => d;
         `(失败态)如果函数没有写,那就把错误抛出去 `
        onRejected = typeof onRejected === 'function' ? onRejected : e => {throw e};
        ` 规范上写调用.then 时必须返回 promise`
        let promise2 = new Promise((resolve, reject) => {
        ` 如果状态为成功态 `
            if (this.status === FULFILLED) {setTimeout(() => {
                    try {
                    ` 接受.then 后面第一个函数的返回值,为了判断有没有抛错使用了 try 包裹 `
                        let x = onFulfilled(this.value);
                        ` 判断 x 是 promise 还是普通值,从而进行不同的处理,当调用这个函数时获取不到 promise 所以这里使用了异步 `
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                    ` 如果抛错之后调用 reject 方法以 e 作为原因 `
                        reject(e)
                    }
                }, 0);
            }
            if (this.status === REJECTED) {setTimeout(() => {
                    try {let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {reject(e)
                    }
                }, 0);
            }
            if (this.status === PENDING) {
          ` 如果是异步的话,使用发布订阅模式,将事件放到对应的事件池中 `
                this.onFulfilledCallbacks.push(() => {setTimeout(() => {
                        try {let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {reject(e)
                        }
                    }, 0)
                });
                this.onRejectedCallbacks.push(() => {setTimeout(() => {
                        try {let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {reject(e)
                        }
                    }, 0)
                })
            }
        });
        return promise2;// 返回一个 promise
    }
}

// 导出我们自己写的 promise
module.exports = Promise;

测试

1. 安装测试脚本

npm i -g promises-aplus-tests

2. 在我们写的 promise 中写入代码

// 测试代码
Promise.defer = Promise.deferred = function () {let dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd
}

3. 在当前文件夹下执行

promises-aplus-tests xxx.js(自己写 promise 的文件)
退出移动版