手写Promise,通过Promise/A+的872个测试

github博客Promise的声明当我们使用Promise的时候,通常都是new Promise((resolve, reject) => {})。因此我们可以看出:Promise是一个类;Promise类的构造函数的第一个参数是函数,这个函数叫处理器函数(executor function);而在处理器函数中,有了两个参数:resolve和reject当异步任务顺利完成且返回结果值的时候,我们会调用resolve函数;当异步任务失败且返回失败原因(通常是一个错误对象).
摘要由CSDN通过智能技术生成

github

博客

Promise的声明

当我们使用Promise的时候,通常都是new Promise((resolve, reject) => {})

因此我们可以看出:

  • Promise是一个类;
  • Promise类的构造函数的第一个参数是函数,这个函数叫处理器函数(executor function);
  • 而在处理器函数中,有了两个参数:resolvereject
    • 当异步任务顺利完成且返回结果值的时候,我们会调用resolve函数;
    • 当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject函数。

因此,我们可以初步声明一下Promise类。

class Promise {
   
    /**
     * 构造器
     * @returns {Promise<object>}
     * @param executor<function>: executor有两个参数:resolve和reject
     */
    constructor(executor) {
   
        // resolve 成功
        const resolve = () => {
   };

        // reject 失败
        const reject = () => {
   };

        // 执行 executor
        executor(resolve,reject);
    }
}

实现Promise的基本状态

Promise存在着三种状态:pending(等待态)、fulfilled(成功态)和rejected(失败态):

  • Promise的初始状态是pending状态;
  • pending状态可以转换为fulfilled状态和rejected状态;
  • fulfilled状态不可以转为其他状态,且必须有一个不可改变的值(value);
  • rejected状态不可以转为其他状态,且必须有一个不可改变的原因(reason);
  • 当在处理器函数中调用resolve函数并传入参数value,则状态改变为fulfilled,且不可以改变;
  • 当在处理器函数中调用reject函数并传入参数reason,则状态改变为rejected,且不可以改变;
  • 若处理器函数执行中报错,直接执行reject函数。

因此,我们需要在Promise类中设置三个变量:state(状态变量),value(成功值的变量)和reason(失败原因的变量),然后在resolve函数、reject函数以及执行executor函数报错的时候改变state的值。

class Promise {
   
    constructor(executor) {
   
        // 初始化状态
        this.state = 'pending';
        // 成功的值
        this.value = undefined;
        // 失败的原因
        this.reason = undefined;
        
        /**
         * resolve 成功函数
         * @param value<any>: 成功的值
         */
        const resolve = (value) => {
   
            // 只能在状态为pending的时候执行
            if(this.state === 'pending'){
   
                // resolve调用后,state转化为fulfilled
                this.state = 'fulfilled';
                // 存储value
                this.value = value;
            }
        };

        /**
         * reject 失败函数
         * @param reason<any>: 失败的原因
         */
        const reject = (reason) => {
   
            // 只能在状态为pending的时候执行
            if(this.state === 'pending'){
   
                // resolve调用后,state转化为rejected
                this.state = 'rejected';
                // 存储reason
                this.reason = reason;
            }
        };

        // 如果executor执行报错,直接执行reject()
        try {
   
            executor(resolve,reject);
        }catch (e){
   
            reject(e);
        }
    }
}

then方法

Promise有一个then方法,而该方法中有两个参数:onFulfilledonRejected

  • 这两个参数都是一个函数,且会返回一个结果值;
  • 当状态为fulfilled,只执行onFulfilled,传入this.value
  • 当状态为rejected,只执行onRejected,传入this.reason

因此我们可以来实现一下then方法。

class Promise {
   
   constructor(executor) {
   ...}

    /**
     * then 方法
     * @param onFulfilled<function>: 状态为fulfilled时调用
     * @param onRejected<function>: 状态为rejected时调用
     */
    then(onFulfilled, onRejected) {
   
        // 状态为fulfilled的时候,执行onFulfilled,并传入this.value
        if(this.state === 'fulfilled'){
   
            /**
             * onFulfilled 方法
             * @param value<function>: 成功的结果
             */
            onFulfilled(this.value)
        }

        // 状态为rejected的时候,onRejected,并传入this.reason
        if(this.state === 'rejected'){
   
            /**
             * onRejected 方法
             * @param reason<function>: 失败的原因
             */
            onRejected(this.reason)
        }
    }
}

异步实现

Promise实际上一个异步操作:

  • resolve()是在setTimeout内执行的;
  • 当执行then()函数时,如果状态是pending时,我们需要等待状态结束后,才继续执行,因此此时我们需要将then()的两个参数onFulfilledonRejected存起来;
  • 因为一个Promise实例可以调用多次then(),因此我们需要将onFulfilledonRejected各种用数组存起来。

因此我们可以借着完善代码:

class Promise {
   
    /**
     * 构造器
     * @returns {Promise<object>}
     * @param executor<function>: executor有两个参数:resolve和reject
     */
    constructor(executor) {
   
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;
        // 存储onFulfilled的数组
        this.onResolvedCallbacks = [];
        // 存储onRejected的数组
        this.onRejectedCallbacks = [];

        const resolve = (value) => {
   
            if (this.state === 'pending') {
   
                this.state = 'fulfilled';
                this.value = value;
                // 一旦resolve执行,调用onResolvedCallbacks数组的函数
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };

        const reject = (reason) => {
   
            if (this.state === 'pending') {
   
                this.state = 'rejected';
                this.reason = reason;
             
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值