实现手写Promise

在手写Promise之前,需要先了解Promise。

语法:const p = new Promise((resolve,reject)=>{...} )
在创建对象时,传入一个函数参数,同时函数立即执行,函数又接受两个函数作为参数,调用resolve或者reject后状态发生改变且不会再变。

promise有三个状态,分别是pending,fulfilled,rejected,在创建对象之初为pending(待定)状态,调用resolve后变为fullfilled(成功)状态,调用reject后变为rejected(失败)状态。

状态改变后,会调用then方法里的回调。then方法一般接受两个回调函数作为参数,第一个onFulfilled,状态变为fulfilled会执行。第二个onRejected,状态变为rejected会执行。均返回一个新的promise对象,返回的promise对象状态与传的参数有关,这里不再细分,以后再说。

catch方法等同于then方法里rejected的回调,如果任务处于rejected状态则就不在执行then回调,而是去执行catch的回调。

then或catch方法里的回调,会将任务放到微队列去执行。

好,明白了promise的大体步骤,再来看怎么去手写一个promise。

这是一个符合Promise/A+的代码,具体我也说不上来,只能多看几遍,明白了其原理还是挺简单的。

// 定义三种状态
const PENDING = 'pending'; // 初始状态,等待
const FULFILLED = 'fulfilled'; // 成功状态
const REJECTED = 'rejected'; // 失败状态

// Promise构造函数
function Promise(executor) {
    var _this = this; // 当前的promise实例
    this.state = PENDING; // 初始化状态为等待
    this.value = undefined; // 成功时的值
    this.reason = undefined; // 失败时的理由

    this.onFulfilled = []; // 成功的回调函数列表
    this.onRejected = []; // 失败的回调函数列表

    // 成功解决时的处理函数
    function resolve(value) {
        if (_this.state === PENDING) {
            _this.state = FULFILLED; // 状态改为成功
            _this.value = value; // 成功时的值设为传入的value
            _this.onFulfilled.forEach(fn => fn(value)); // 执行所有的成功回调
        }
    }

    // 拒绝promise时的处理函数
    function reject(reason) {
        if (_this.state === PENDING) {
            _this.state = REJECTED; // 状态改为失败
            _this.reason = reason; // 失败时的理由设为传入的原因
            _this.onRejected.forEach(fn => fn(reason)); // 执行所有的失败回调
        }
    }

    // 尝试执行executor,并捕获可能出现的异常
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e); // 如果executor中有异常,直接拒绝promise
    }
}

// 提供一个deferred API,等价于Promise.defer或Promise.deferred
Promise.defer = Promise.deferred = function () {
    let dfd = {}; // 创建一个对象来保存结果和回调
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve; // 保存解决函数
        dfd.reject = reject; // 保存拒绝函数
    });
    return dfd; // 返回这个deferred对象
}

// 原型上的then方法,允许添加成功和失败的回调
Promise.prototype.then = function (onFulfilled, onRejected) {
    // onFulfilled和onRejected如果不是函数,则默认分别返回value和抛出reason
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

    // 创建一个新的promise
    var promise2 = new Promise((resolve, reject) => {
        if (_this.state === FULFILLED) {
            // 如果当前状态是成功,则异步执行onFulfilled,并将结果 resolve(promise2)
            setTimeout(() => {
                try {
                    let x = onFulfilled(_this.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error);
                }
            });
        } else if (_this.state === REJECTED) {
            // 如果当前状态是失败,则异步执行onRejected,并将结果 resolve(promise2)
            setTimeout(() => {
                try {
                    let x = onRejected(_this.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error);
                }
            });
        } else if (_this.state === PENDING) {
            // 如果当前状态是等待,则将onFulfilled和onRejected函数存起来
            _this.onFulfilled.push(() => {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(_this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            });
            _this.onRejected.push(() => {
                setTimeout(() => {
                    try {
                        let x = onRejected(_this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            });
        }
    });

    // 返回新的promise
    return promise2;
};

// resolvePromise的辅助函数,用于正确处理promise的链式调用
function resolvePromise(promise2, x, resolve, reject) {
    // 如果promise2和x相同,则拒绝promise,防止循环引用
    if (promise2 === x) {
        reject(new TypeError('Chaining cycle'));
    }
    // 如果x是一个对象或者函数
    if (x && (typeof x === 'object' || typeof x === 'function')) {
        // 尝试获取x的then方法
        let used;
        try {
            let then = x.then;
            if (typeof then === 'function') {
                // 如果是thenable,则使用它的then方法,并处理返回的结果
                then.call(
                    x,
                    y => {
                        if (used) return;
                        used = true;
                        resolvePromise(promise2, y, resolve, reject);
                    },
                    r => {
                        if (used) return;
                        used = true;
                        reject(r);
                    }
                );
            } else {
                // 如果x是一个普通对象,直接resolve
                resolve(x);
            }
        } catch (e) {
            if (used) return;
            used = true;
            reject(e);
        }
    } else {
        // 如果x不是对象或函数,直接resolve
        resolve(x);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值