当前位置: 移动技术网 > IT编程>脚本编程>vue.js > 手写Promise(个人笔记)

手写Promise(个人笔记)

2020年10月29日  | 移动技术网IT编程  | 我要评论
手写Promise第一步:先声明一个类,以及一些需要用到的属性;说明:首先我们最常用promise的几个方法resolve,reject,then我们需要先定义出来,另外我们要知道promise是异步操作,而异步操作都是有最基本的三种状态的(等待,成功,失败),所以状态我们也需要定义。另外,声明一个promise实例时,我们会向它的构造函数中传入一个函数,这个函数是会立即执行的,并且会将resolve,reject两个方法当作参数传递进去。第二步:resolve和reject方法中需要做哪些事情

一步一步手写Promise

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

第一步:先声明一个类,以及一些需要用到的属性、方法;

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

第二步:resolve、reject和then方法中需要做哪些事情(暂时不考虑异步情况)
在这里插入图片描述

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

第三步:异步情况下resolve、reject和then的处理方式。
在这里插入图片描述

说明:其实加入异步逻辑过后的代码也非常简单,无非是在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
在这里插入图片描述

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

ok,大功告成,end!

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网