Promise源码解析

时间:2025-01-18 16:13:28

 Promise分析:
  就是一个类 在执行这个类的时候,需要传递一个执行器进去,执行器会立即执行
  中有三种状态 分别为 成功fulfilled 失败rejected 等待pendeng
    pending -> fulfilled
    pending -> rejected
    一旦状态确定就不可更改
 和reject函数是用来更改状态的
    resolve: fulfilled
    reject: rejected
 方法内部做的事情就是判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败的回调函数
    then方式是被定义在原型对象中的
 成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败的原因

// promise 原理代码
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) { // 接收执行器
        try {
            executor(, )
        } catch (e) {
            (e);
        }
    }
    
    status = PENDING; // promise的状态
    value = undefined; // 成功之后的值
    reason = undefined; // 失败之后的值
    successCallback = []; // 成功回调
    failCallback = []; // 失败回调

    // resolve和reject为什么要用箭头函数?
    // 如果直接调用的话,普通函数this指向的是window或者undefined
    // 用箭头函数就可以让this指向当前实例对象
    resolve = value => {
        // 如果状态不是等待 组织程序向下执行
        if ( !== PENDING) return
        // 将状态更改为成功
         = FULFILLED;
        // 保存成功之后的值
         = value;
        // 判断成功回调是否存在 如果存在 调用
        // && ()
        while () ()()
    }
    reject = reason => {
        // 如果状态不是等待 组织程序向下执行
        if ( !== PENDING) return
        // 将状态更改为失败
         = REJECTED;
        // 保存失败后的原因
         = reason;
        // 判断失败回调是否存在 如果存在 调用
        //  && ()
        while () ()();
    }

    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => {
            throw reason
        }; // then链式调用参数变为可选参数 例:().then().then((value)=>{(value)}) // value
        let promise2 = new MyPromise((resolve, reject) => {
            // 传递一个执行器 立马执行
            // 判断状态
            if ( === FULFILLED) {
                setTimeout(() => { // 将下面的代码变成异步代码
                    try {
                        let x = successCallback()
                        // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve
                        // 如果是promise对象 查看promise对象返回的结果
                        // 再根据promise对象返回的结果 界定调用resolve 还是reject
                        resolvePromise(x, resolve, reject);
                    } catch (e) { // 处理异常状态
                        reject(e)
                    }
                }, 0)
            } else if ( === REJECTED) {
                setTimeout(() => { // 将下面的代码变成异步代码
                    try {
                        let x = failCallback()
                        resolvePromise(x, resolve, reject);
                    } catch (e) { // 处理异常状态
                        reject(e)
                    }
                }, 0)
            } else {
                // 当前状态是等待
                // 将成功回调和失败回调存储起来 - 多个then方法调用
                (() => {
                    setTimeout(() => { // 将下面的代码变成异步代码
                        try {
                            let x = successCallback();
                            resolvePromise(x, resolve, reject);
                        } catch (e) { // 处理异常状态
                            reject(e)
                        }
                    }, 0)
                });
                (() => {
                    setTimeout(() => { // 将下面的代码变成异步代码
                        try {
                            let x = failCallback();
                            resolvePromise(x, resolve, reject);
                        } catch (e) { // 处理异常状态
                            reject(e)
                        }
                    }, 0)
                });

            }
        });
        return promise2;
    }

    finally(callback) {
        /**
         - 无论当前最终状态是成功还是失败,finally都会执行
         - 我们可以在finally方法之后调用then方法拿到结果
         - 这个函数是在原型对象上用的
         * **/
        return (value => {
            return (callback()).then(() => value)
        }, reason => {
            return (callback()).then(() => {
                throw reason
            })
        })
    }

    catch(failCallback) {
        /**
         - catch方法是为了捕获promise对象的所有错误回调的
         - 直接调用then方法,然后成功的地方传递undefined,错误的地方传递reason
         - catch方法是作用在原型对象上的方法
         * **/
        return (undefined, failCallback);
    }

    static all(array) {
        /**
         * 分析一下:
         - all方法接收一个数组,数组中可以是普通值也可以是promise对象
         - 数组中值得顺序一定是我们得到的结果的顺序
         - promise返回值也是一个promise对象,可以调用then方法
         - 如果数组中所有值是成功的,那么then里面就是成功回调,如果有一个值是失败的,那么then里面就是失败的
         - 使用all方法是用类直接调用,那么all一定是一个静态方法
         **/
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            function addData(key, value) {
                // 保存每个传入参数执行完毕,并存储返回值
                result[key] = value;
                index++;
                if (index === ) {
                    resolve(result)
                }
            }

            for (let i = 0; i < ; i++) {
                let current = array[i];
                if (current instanceof MyPromise) {
                    // promise对象
                    (value => addData(i, value), reason => reject(reason))
                } else {
                    // 普通值
                    addData(i, array[i])
                }
            }
        })
    }

    static resolve(value) {
        /**
         resolve方法的作用是将给定的值转换为promise对象 resolve的返回值的promise对象
         如果参数就是一个promise对象,直接返回,如果是一个值,那么需要生成一个promise对象,把值进行返回
         是Promise类的一个静态方法
         * **/
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value))
    }
}

function resolvePromise(x, resolve, reject) {
    if (x instanceof MyPromise) {
        // promise 对象
        // ( value => resolve(value),reason => reject(reason))
        (resolve, reject)  // 简化
    } else {
        // 普通值
        resolve(x)
    }
}

 = MyPromise;

测试案例:

let promise = new MyPromise((resolve,reject)=>{
    // setTimeout(()=>{ // 异步操作
    //     resolve('成功')
    // },2000)
    resolve('成功')
})
let p1 = (value =>{
    (value)
    return p1
})

// 测试 then方法可以多次调用
// then 方法的链式调用 1.实现链式调用 2.将一个返回值作为第二个then的参数
(value => {
    (value);
    return p1
},reason => {
    (reason)
}).then(value => {
    (value)
})
// 打印结果-> 成功 成功
function f1() {
    return new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            resolve('f1')
        },2000)
    })
}
function f2() {
    return new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            resolve('f2')
        },0)
    })
}

// - 测试方法
(['a','b',f1(),f2(),'c']).then(function (result) {
    (result);
})

// 打印结果-> a b f1 f2 c

// - 测试 方法
f2().finally(()=>{
    ('finally')
}).then((value => {
    (value)
}), reason =>{
    (reason)
})
// 打印结果-> flnally f2

// 测试 方法
('100').then(value => (value))  // 打印结果-> 100
(f1()).then(value => (value)) // 打印结果-> f1
function f2() {
    return new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            reject('f2---fail');
        },0)
    })
}

// 测试 方法
f2().then(value => {(value)})
    .catch(reason => {(reason)})

// 打印结果-> f2---fail