[JavaScript]根据PromiseA+规范手写Promise

一、Promise的声明

首先呢,Promise肯定是一个类,我们就用class来声明。
• 由于 new Promise((resolve, reject)=>{}) ,所以传入一个参数(函数),PromiseA+里叫他executor(作业执行器),传入就执行。
executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
•由于resolvereject可执行,所以都是函数,我们用let声明。

        class Promise {
            // 构造器
            constructor(executor) {
                // 成功
                let resolve = () => {};
                // 失败
                let reject = () => {};
                // 立即执行
                executor(resolve, reject);
            }
        }

二、解决基本状态

PromiseA+Promise有规定:

  • Promise存在三个状态(statependingfulfilledrejected
  • pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
  • 成功时,不可转为其他状态,且必须有一个不可改变的值(value
  • 失败时,不可转为其他状态,且必须有一个不可改变的原因(reason
  • new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
  • new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
  • 若是executor函数报错 直接执行reject();
    于是乎,我们获得以下代码:
        class Promise {
            // 构造器 
            constructor(executor) {
                // 初始化state为等待态
                this.state = 'pending'
                // 成功的值
                this.value = undefined
                // 失败的原因
                this.reason = undefined

                // 成功
                let resolve = value => {
                    // state改变,resolve调用就会失败
                    if (this.state === 'pending') {
                        // resolve调用后,state转化为成功态
                        this.state = 'fulfilled'
                        // 储存成功的值
                        this.value = value
                    }
                }
                // 失败
                let reject = reason => {
                    // state改变,reject调用就会失败
                    if (this.state === 'pending') {
                        // reject调用后,state转化为失败态
                        this.state = 'rejected'
                        // 储存失败的原因
                        this.reason = reason
                    }
                }

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

三、then方法

PromiseA+规定:Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
•当状态statefulfilled,则执行onFulfilled,传入this.value。当状态staterejected,则执行onRejected,传入this.value
onFulfilled,onRejected如果他们是函数,则必须分别在fulfilledrejected后被调用,valuereason依分别为他们的第一个参数

        class Promise {
            // 构造器 
            constructor(executor) {...}
            
            // then方法 有两个参数 onFulfilled onRejected
            then(onFulfilled, onRejected) {
                // 状态为fulfilled,执行onFulfilled,传入成功的值
                if (this.state === 'fulfilled') {
                    onFulfilled(this.value)
                }
                if (this.state === 'rejected') {
                    onRejected(this.reason)
                }
            }
        }

四、解决异步实现

现在基本可以实现简单的同步代码,但是当resolvesetTomeout内执行,thenstate还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们

类似于发布订阅,先将then里面的两个函数储存起来,由于一个Promise可以有多个then,所以存在同一个数组内。

		// 多个then的情况
        let p = new Promise();
        p.then();
        p.then();

成功或者失败时,forEach调用它们

        class Promise {
            // 构造器 
            constructor(executor) {
                // 初始化state为等待态
                this.state = 'pending'
                // 成功的值
                this.value = undefined
                // 失败的原因
                this.reason = undefined

                /* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
                // 成功存放的数组     
                this.onResolvedCallbacks = []
                // 失败存放的数组
                this.onRejectedCallbacks = []
                /* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */

                // 成功
                let resolve = value => {
                    // state改变,resolve调用就会失败
                    if (this.state === 'pending') {
                        // resolve调用后,state转化为成功态
                        this.state = 'fulfilled'
                        // 储存成功的值
                        this.value = value

                        /* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
                        // 一旦resolve执行,调用成功数组的函数
                        this.onResolvedCallbacks.forEach(fn=>fn())
                        /* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
                    }
                }
                // 失败
                let reject = reason => {
                    // state改变,reject调用就会失败
                    if (this.state === 'pending') {
                        // reject调用后,state转化为失败态
                        this.state = 'rejected'
                        // 储存失败的原因
                        this.reason = reason

                        /* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
                        // 一旦reject执行,调用失败数组的函数
                        this.onRejectedCallbacks.forEach(fn=>fn())
                        /* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */                       
                    }
                }

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

            // then方法 有两个参数 onFulfilled onRejected
            then(onFulfilled, onRejected) {
                // 状态为fulfilled,执行onFulfilled,传入成功的值
                if (this.state === 'fulfilled') {
                    onFulfilled(this.value)
                }
                if (this.state === 'rejected') {
                    onRejected(this.reason)
                }
                                       
                /* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */       
                // 当状态为pending时
                if(this.state ==='pending'){
                    // onFullfilled传入到成功数组
                    this.onRejectedCallbacks.push(()=>{
                        onFullfilled(this.value)
                    })
                    // onRejected传入到失败数组
                    this.onRejectedCallbacks.push(()=>{
                        onRejected(this.reason) // 原文中这里写的是value,我认为是reason
                    })
                }
                /* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
            }
        }

五、解决链式调用

我们常常用到 new Promise().then().then() ,这就是链式调用,用来解决回调地狱

1、为了达成链式,我们默认在第一个then里返回一个promisePromiseA+规定了一种方法,就是在then里面返回一个新的promise,称为promise2promise2 = new Promise((resolve, reject)=>{})
•将这个promise2返回的值传递到下一个then
•如果返回一个普通的值,则将普通的值传递给下一个then

2、当我们在第一个thenreturn 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()onRejected()的值

PromiseA+则规定onFulfilled()onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise

        class Promise {
            constructor(executor) {
                this.state = 'pending';
                this.value = undefined;
                this.reason = undefined;
                this.onResolvedCallbacks = [];
                this.onRejectedCallbacks = [];
                let resolve = value => {
                    if (this.state === 'pending') {
                        this.state = 'fulfilled';
                        this.value = value;
                        this.onResolvedCallbacks.forEach(fn => fn());
                    }
                };
                let reject = reason => {
                    if (this.state === 'pending') {
                        this.state = 'rejected';
                        this.reason = reason;
                        this.onRejectedCallbacks.forEach(fn => fn());
                    }
                };
                try {
                    executor(resolve, reject);
                } catch (err) {
                    reject(err);
                }
            }
            then(onFulfilled, onRejected) {
                // 声明返回的promise2
                let promise2 = new Promise((resolve, reject) => {
                    if (this.state === 'fulfilled') {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    };
                    if (this.state === 'rejected') {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    };
                    if (this.state === 'pending') {
                        this.onResolvedCallbacks.push(() => {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        })
                        this.onRejectedCallbacks.push(() => {
                            let x = onRejected(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        })
                    }
                });
                // 返回promise2,完成链式
                return promise2;
            }
        }

完成resolvePromise函数以及更多实现参考原文:
https://www.cnblogs.com/sugar-tomato/p/11353546.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值