【polar的复习笔记】——js基础之promise

112 阅读3分钟

个人简介:

大家好,我是polar,一个 前端攻城狮/动漫爱好者/科技控/AI观察家/95%的素食主义者/,欢迎大家来找我扩列,一起愉快玩耍。

从今天起,我会开始更新一个系列【polar的复习笔记】,用于总结梳理相关的知识点,构建前端知识图谱,也同时欢迎大家一起来探讨交流。

下面一起来复习一下promise:

promise的特点

  1. promise 是一个构造函数,默认需要传入一个executor执行器
  2. executor会立刻执行,并传入 resolve 和 reject 两个参数
  3. promise 有三种状态 fulfilled 成功 reject 拒绝态 pending 等待态
  4. 每个promise都有一个then方法,可以访问到成功或者失败的原因
  5. 可以通过resolve和reject来改变状态,同时调用对应的回调
  6. 当executor 发生异常的时候,也会触发promise的失败

promise then链的特点

  1. then链的特点,当then中成功和失败的回调函数返回的是一个promise,内部会解析这个promise,并将结果传递到外层的下一个then
  2. 下一次then走成功还是失败,取决于当前的promise状态
  3. 如果then返回的不是一个promise,那么这个结果会直接传递到下一个then的成功
  4. 如果then的回调中抛异常了,那么会执行下一个then的失败

一个完整符合promiseA+规范的promise实现如下:

const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';


// 为了所有then的promise都可以相互调用,所以所有的promise都要遵循这个规则
function resolvePromise (promise2, x, resolve, reject) {
    // 这个方法会处理的严谨一些,保证所有人的promise可以相互调用
    // 自己等自己会循环卡死
    if (x === promise2) {
        return reject(TypeError('cycle error'));
    }
    // 判断是不是promise
    if ((typeof x === 'object' && x) || (typeof x === 'function')) {
        let called = false;
        // 有可能是promise
        // 之所以catch,是因为可能有代理(defineProperty)
        try {
            let then = x.then;
            if (typeof then === 'function') {
                // 是promise
                then.call(x, (y)=> {
                    if (called) return;
                    called = true;
                    // resolve(y);
                    // 排除y还是promise的情况,使用resolvePromise递归解析
                    resolvePromise (promise2, y, resolve, reject)
                }, (r)=>{
                    if (called) return;
                    called = true;
                    reject(r);
                });
            } else {
                if (called) return;
                called = true;
                // 是对象或者函数
                resolve(x);
            }
        } catch (e) {
            reject(e);
        }
    } else {
        resolve(x); // 普通值,直接将结果传递到下面
    }
}

class Promise {
    constructor (executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;

        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        // promise 调用 this的时候,状态可能依旧是 pending,那么我们需要先将回调存放起来
        // 等resolve触发的时候,onResolvedCallbacks 执行
        // 调用reject的时候,onRejectedCallbacks 执行

        const resolve = (value) => {
            if (this.status === PENDING) {
                // 只有状态是pending的时候,才能修改状态和 改变是成功和失败的原因
                this.status = FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(item => {
                    item();
                })
            }
        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks.forEach(item => {
                    item();
                })
            }
        }
        // 调用executor 会自动传入 resolve 和 reject
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
    }
    then (onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v=>v;
        onRejected = typeof onRejected === 'function' ? onRejected : e=>{throw e};

        let promise2 = new Promise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    } 
                });
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            }
            if (this.status === PENDING) {
                // this.onResolvedCallbacks.push(onFulfilled);
                // this.onRejectedCallbacks.push(onRejected);
    
                // 为了在调用函数之前做些处理,使用一个函数将其包起来
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject); 
                        } catch (e) {
                            reject(e);
                        }
                    });
                })
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    });
                })
            }
        })
        return promise2;
    }
}

module.exports = Promise;