欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

手写Promise(个人笔记)

程序员文章站 2022-04-12 08:10:06
手写Promise第一步:先声明一个类,以及一些需要用到的属性;说明:首先我们最常用promise的几个方法resolve,reject,then我们需要先定义出来,另外我们要知道promise是异步操作,而异步操作都是有最基本的三种状态的(等待,成功,失败),所以状态我们也需要定义。另外,声明一个promise实例时,我们会向它的构造函数中传入一个函数,这个函数是会立即执行的,并且会将resolve,reject两个方法当作参数传递进去。第二步:resolve和reject方法中需要做哪些事情...

一步一步手写Promise

本人笔记,有不对的地方欢迎指正,谢谢各位大佬。

第一步:先声明一个类,以及一些需要用到的属性、方法;
手写Promise(个人笔记)

说明:首先我们最常用promise的几个方法resolve,reject,then我们需要先定义出来,另外我们要知道Promise是异步操作,而异步操作都是有最基本的三种状态的(等待,成功,失败),所以状态我们也需要定义。另外,声明一个Promise实例时,我们会向它的构造函数中传入一个执行器,这个执行器是立即执行的,并且会将resolve,reject两个方法当作参数传递进去。还有就是then方法的声明要注意,then方法是在实例上调用的,所以需要将它声明在类的原型上

第二步:resolve、reject和then方法中需要做哪些事情(暂时不考虑异步情况)
手写Promise(个人笔记)

说明:其实resolve和reject要做的事情很简单,只需要将promise的状态改为成功或者失败,并将传入的值保存起来就ok了。但是需要注意的是,Promise的状态一旦确定为成功或者失败,就不可再更改状态,所以需要在resolve和reject方法的开始必须加上一个状态的判断,大家有时间可以去试一下,运行了resolve过后再运行reject是不会生效的。最后then方法中直接将保存下来的值传入相对应的方法中执行即可。当然,这是在不考虑异步情况下可以这样想,但是不考虑异步的话,Promise也没啥存在的意义,这里主要是方便理解整个promise的执行流程。接下来,改造一下这个方法来实现真正的Promise。

第三步:异步情况下resolve、reject和then的处理方式。
手写Promise(个人笔记)

说明:其实加入异步逻辑过后的代码也非常简单,无非是在then方法中将两种状态下的回调函数也保存起来,然后在执行resolve的时候将其执行即可。但是还有一点没有考虑到,就是then方法的链式调用。我们知道Promise声明后,then方法是可以在其实例对象上进行链式调用的,这就说明会有多个处理函数需要执行,下面我们继续来改造。

第四步:实现then方法的链式调用。

实现链式调用之前我们需要了解链式调用的原理:每一个then传入的值都是上一个then方法的返回值,而这就说明每一个返回值都应该支持调用then这个方法,所以,我们每一个then最后返回的都应该是一个Promise对象。(因为代码比较长了,用代码块来展示)

// 先定义Promise类的三种状态
const PENDING = "pengding";
const SUCCESS = "success";
const ERROR = "error";

class MyPromise {
    constructor (fun) {
        fun(this.resolve, this.reject);
    }

    status = PENDING; // 初始化promise的状态为pending
    value = undefined; // 成功后的值
    reason = undefined; // 失败后的原因
    successCallback = [];
    errorCallback = [];


    resolve = value => {
        // 判断状态是否为等待,如果不是则直接return
        if (this.status !== PENDING) return;
        // 将promise的状态设置为成功
        this.status = SUCCESS;
        // 将成功后的值保存起来
        this.value = value;
        // 执行成功回调函数
        while (this.successCallback.length) this.successCallback.shift()(value);
    }

    reject = reason => {
        // 判断状态是否为等待,如果不是则直接return
        if (this.status !== PENDING) return;
        // 将promise的状态设置为成功
        this.status = ERROR;
        // 将成功后的值保存起来
        this.reason = reason;
        // 执行失败回调函数
        while (this.errorCallback.length) this.errorCallback.shift()(reason);
    }

    then (successCallback, errorCallback) {
        let promise2 = new MyPromise((resolve, reject) => {
            if (this.status === SUCCESS) {
                setTimeout(() => {
                    let x = successCallback(this.value);
                    // 判断x是普通值还是promise对象
                    // 如果是普通值,直接调用resolve
                    // 如果是promise对象,查看promise对象返回的结果
                    // 再根据promise对象返回的结果,决定调用resolve还是reject
                    resolvePromise(promise2, x, resolve, reject);
                }, 0);
            } else if (this.status === ERROR) {
                setTimeout(() => {
                    let x = errorCallback(this.resonse);
                    resolvePromise(promise2, x, resolve, reject);
                },0)
            } else {
                this.successCallback.push(() => {
                    setTimeout(() => {
                        let x = successCallback(this.value); 
                        resolvePromise(promise2, x, resolve, reject);
                    }, 0);
                });
                this.errorCallback.push(() => {
                    setTimeout(() => {
                        let x = errorCallback(this.resonse);
                        resolvePromise(promise2, x, resolve, reject);
                    }, 0);
                });
            }
        });
        return promise2;
    }
    catch (fallCallback) {
        return this.then(undefined, fallCallback);
    }
}

function resolvePromise (promise, x, resolve, reject) {
	// 这里排除掉promise自己返回自己的问题
    if (promise === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>').message);
    }
    if (x instanceof MyPromise) {
        x.then(resolve, reject);
    } else {
        resolve(x);
    }
}

说明:then的链式调用主要是将每一个then的返回值封装成一个promise,然后再调用这个promise的then方法去继续执行,所以在then方法中我们声明了一个promise2对象,在这个Promise的执行器里我们再去执行上一个promise的then方法中需要做的事情。其他的问题在注释中已经写的比较清楚了。最后我们顺带实现了一个catch方法,因为这个方法是打印Promise中的一些失败的信息,所以很简单,只需要在内部调用then方法并只传入失败回调函数即可。

第五步:扩展Promise的两个静态函数all、resolve
手写Promise(个人笔记)

说明:首先大家要先搞清楚这两个静态方法的使用,这里就不过多介绍了,大家可以自行去查资料看一下。all方法中主要是先将传入的数组遍历,拿到每一项的值后先判断是否为Promise对象,如果是,则执行它的then方法,拿到它的返回值,然后通过addData方法添加到需要返回的数组里面,如果不是则直接将值添加到返回数组中。resolve方法就非常简单了,同样先判断是否为Promise对象,如果是直接返回这个对象,如果不是,则包裹到Promise中进行返回。

ok,大功告成,end!

本文地址:https://blog.csdn.net/qq_24719349/article/details/109281322