当前位置: 首页 > article >正文

Promise自定义封装

目录

Promise构造函数

then方法封装

catch方法封装

resolve方法封装

reject方法封装

all方法封装

race方法封装


这篇文章主要是介绍如何自己封装Promise构造函数以及其相应的方法。Promise是JS中的重点,很多的面试都会问到。因此需要对其有比较深入地认识。看这篇文章可能需要你对promise有一定的了解,不然可能会有点吃力。

Promise构造函数

首先需要知道Promise构造函数接受的参数,以及内部执行的逻辑功能。Promise构造函数接受一个函数作为实参。该函数具有两个参数,一个为resolve另一个为reject。当函数内部调用resolve函数是,代表promise实例的状态为fulfilled代表成功,同时可以将成功的值传给该函数。当函数内部调用reject函数时,就会让promise实例的状态为rejected代表失败,同时可以将失败的值传给该函数。

在该构造函数中需要声明resolve函数以及reject函数,resolve函数内部需要先判断实例对象的状态,只有当它的状态不为pending时,才能将该实例的状态变成fulfilled。这一步判断主要是解决实例的状态不能改变的情况,只能从pending到fulfilled或者是从pending到rejected。然后再将对应成功的值赋值该实例的PromiseResult属性。然后当实例的状态改变时它会执行对应then方法中的回调,该回调是在resolve函数中调用的。then方法为异步,因此需要加上该给定时器。同时当实例的状态改变时,该实例对应的多个then方法都会执行,因此可以声明一个用于存储回调函数的数组,然后遍历该数组除了对应的回调。reject函数是同个道理。

function Promise(executor){
    //添加属性
    this.PromiseState='pending';
    this.PromiseResult=null;
    //声明属性 存储回调函数
    this.callBacks=[];
    //保存实例对象的this值
    const self=this;
    //resolve函数
    function resolve(data){
        //判断状态
        if(self.PromiseState!=='pending') return;
        //修改对象的状态(promiseState)
        self.PromiseState='fulfilled';
        //设置对象结果值
        self.PromiseResult=data;
        //调用成功的回调函数
        setTimeout(()=>{
            self.callBacks.forEach(item=>{
                item.onResolved(data);
             })
        });
    }
    //reject函数
    function reject(data){
         //判断状态
         if(self.PromiseState!=='pending') return;
         //修改对象的状态(promiseState)
         self.PromiseState='rejected';
         //设置对象结果值
         self.PromiseResult=data;
         //调用失败的回调
         setTimeout(()=>{
            self.callBacks.forEach(item=>{
                item.onRejected(data);
             })
         });
    }
    try{
        //同步调用
        executor(resolve,reject);

    }catch(e){
        //修改promise对象状态为失败
        reject(e);
    }

}

then方法封装

当promise实例状态发生改变时then方法会被调用。then方法传入两个参数,第一个参数是resolved状态的回调函数,当实例的状态为成功时执行该函数。第二个参数是rejected状态的回调函数,当实例的状态为失败时执行该函数。then方法返回的是一个新的Promise实例。该实例对象的状态由回调函数的执行结果决定。如果回调函数中返回的结果是非promise类型的属性,状态为成功,返回的值为对象的成功的值。若没有return返回结果,则同样是成功的状态,只是对应的值为undefined。若返回的是一个promise对象,then返回的状态则为return中promise对象的状态,其值也是对应的内部return中promise的值。若是抛出错误,则then返回的promise对象的状态为失败的状态,对应的值为抛出的值。

then方法中的两个参数当第一个参数没有传入时,默认地给该参数设置为一个携带value参数并返回value的函数。这些做可以实现promise中对应的值传递的功能。当第二个参数没有传值时,我们默认的将该参数赋值为一个携带reason参数并返回reason的函数。这样可以实现promise中的异常穿透的功能。then方法的回调是异步执行的,因此需要在执行回调的时候包裹一个定时器。

当实例对象的状态还是pending时,将对应的回调存放到保存回调函数的数组中。当实例的状态改变时则会进行调用。

Promise.prototype.then=function(onResolved,onRejected){
    const self=this;
    //判断回调函数参数
    if(typeof onRejected !=='function'){
        onRejected=reason=>{
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
    }
    return new Promise((resolve,reject)=>{
        //封装函数
        function callback(type){
            try{
                //获取回调函数的执行结果
                let result=type(self.PromiseResult);
                //判断
                if(result instanceof Promise){
                    //如果是Promise类型的对象
                    result.then(v=>{
                        resolve(v);
                    },r=>{
                        reject(r);
                    })
                }else{
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }

        }
        if(this.PromiseState==='fulfilled'){
            setTimeout(()=>{
                callback(onResolved);
            })
        }
        if(this.PromiseState==='rejected'){
            setTimeout(()=>{
                callback(onRejected);
            })
        }
        if(this.PromiseState==='pending'){
            //保存回调函数
            this.callBacks.push({
                onResolved:function(){
                    callback(onResolved);
                },
                onRejected:function(){
                    callback(onRejected);
                }
            })
            
        }

    });
  
}

catch方法封装

该方法用于处理当promise实例的状态为失败时的回调,相当于是then方法的第二个回调函数。

Promise.prototype.catch=function(onRejected){
    return this.then(undefined,onRejected);
}

resolve方法封装

该方法是Promise构造函数的方法,不是其实例对象的方法。其的作用是返回一个成功的promise对象。若传入的值不是promise,则一定返回成功的状态。当传入的值为Promise对象时,它的状态由传入的promise的状态决定。

Promise.resolve=function(value){
    //返回promise对象
   return new Promise((resolve,reject)=>{
    if(value instanceof Promise){
        value.then(v=>{
            resolve(v);
        },r=>{
            reject(r);
        })
    }else{
        //状态设置为成功
        resolve(value);
    }
   })
}

reject方法封装

该方法是Promise构造函数的方法。其的作用是返回一个失败的promise对象。不管传入的参数是什么,都是返回一个失败状态的promise对象

Promise.reject=function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    })
}

all方法封装

该方法是Promise构造函数的方法。该方法接受多个promise实例。当接收的所有promise实例对象的状态都为成功时才会是成功的状态,返回的结构为所有对象的成功值,存储在数组中。但有其中的一个实例对象的状态为失败时,all方法返回的promise对象的状态会变成失败,且对应的值为其中传入失败的promise对象失败的值。

这里需要声明一个变量来进行记录,但执行成功的回调时就会增加一,当该数值与数组的长度一样时,说明所有的promise实例的状态都为成功。则让其调用成功的回调函数。由于返回的值是原本数组中实例存放的位置,因此需要 arr[i]=v;执行数组的对应下标,存放对应实例的值。

Promise.all=function(promises){
    return new Promise((resolve,reject)=>{
        //声明变量
        let count=0;
        let arr=[];
        //遍历
        for(let i=0;i<promises.length;i++){
            promises[i].then(v=>{
                count++;
                //将当前promise对象成功的结果存入到数组
                arr[i]=v;
                //判断
                if(count==promises.length){
                    //修改状态
                    resolve(arr);
                }
            },r=>{
                reject(r);
            });
        }
    })
}

race方法封装

该方法是Promise构造函数的方法。该方法同样接受多个promise对象。它返回的promise对象的状态以及值,由第一个最先改变状态的promise对象决定

遍历数组之后,此时只需要有一个成功,则就调用成功的回调。

Promise.race=function(promises){
    return new Promise((resolve,reject)=>{
        for(let i=0;i<promises.length;i++){
            promises[i].then(v=>{
                //修改返回对象的状态为成功
                resolve(v);
            },r=>{
                //修改返回对象的状态为失败
                reject(r);
            })
        }
    })
}

class封装

最后将其封装到class中,让其更加地简洁。

class Promise {
    //构造函数
    constructor(executor) {
        //添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        //声明属性 存储回调函数
        this.callBacks = [];
        //保存实例对象的this值
        const self = this;
        //resolve函数
        function resolve(data) {
            //判断状态
            if (self.PromiseState !== 'pending') return;
            //修改对象的状态(promiseState)
            self.PromiseState = 'fulfilled';
            //设置对象结果值
            self.PromiseResult = data;
            //调用成功的回调函数
            setTimeout(() => {
                self.callBacks.forEach(item => {
                    item.onResolved(data);
                })
            });
        }
        //reject函数
        function reject(data) {
            //判断状态
            if (self.PromiseState !== 'pending') return;
            //修改对象的状态(promiseState)
            self.PromiseState = 'rejected';
            //设置对象结果值
            self.PromiseResult = data;
            //调用失败的回调
            setTimeout(() => {
                self.callBacks.forEach(item => {
                    item.onRejected(data);
                })
            });
        }
        try {
            //同步调用
            executor(resolve, reject);

        } catch (e) {
            //修改promise对象状态为失败
            reject(e);
        }

    }
    //then方法
    then(onResolved, onRejected) {
        const self = this;
        //判断回调函数参数
        if (typeof onRejected !== 'function') {
            onRejected = reason => {
                throw reason;
            }
        }
        if (typeof onResolved !== 'function') {
            onResolved = value => value;
        }
        return new Promise((resolve, reject) => {
            //封装函数
            function callback(type) {
                try {
                    //获取回调函数的执行结果
                    let result = type(self.PromiseResult);
                    //判断
                    if (result instanceof Promise) {
                        //如果是Promise类型的对象
                        result.then(v => {
                            resolve(v);
                        }, r => {
                            reject(r);
                        })
                    } else {
                        resolve(result);
                    }
                } catch (e) {
                    reject(e);
                }

            }
            if (this.PromiseState === 'fulfilled') {
                setTimeout(() => {
                    callback(onResolved);
                })
            }
            if (this.PromiseState === 'rejected') {
                setTimeout(() => {
                    callback(onRejected);
                })
            }
            if (this.PromiseState === 'pending') {
                //保存回调函数
                this.callBacks.push({
                    onResolved: function () {
                        callback(onResolved);
                    },
                    onRejected: function () {
                        callback(onRejected);
                    }
                })

            }

        });

    }
    //catch方法
    catch(onRejected) {
        return this.then(undefined, onRejected);
    }

    //添加resolve方法
    static resolve(value) {
        //返回promise对象
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                })
            } else {
                //状态设置为成功
                resolve(value);
            }
        })
    }

    //添加reject方法
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        })
    }

    //添加all方法
    static all(promises) {
        return new Promise((resolve, reject) => {
            //声明变量
            let count = 0;
            let arr = [];
            //遍历
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    count++;
                    //将当前promise对象成功的结果存入到数组
                    arr[i] = v;
                    //判断
                    if (count == promises.length) {
                        //修改状态
                        resolve(arr);
                    }
                }, r => {
                    reject(r);
                });
            }
        })
    }

    //添加race方法
    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    //修改返回对象的状态为成功
                    resolve(v);
                }, r => {
                    //修改返回对象的状态为失败
                    reject(r);
                })
            }
        })
    }

}

好啦!本文就到这里了。拜拜~~


http://www.kler.cn/a/156036.html

相关文章:

  • 大数据技术之HBase中的HRegion
  • [CKS] 关闭API凭据自动挂载
  • Unity资源打包Addressable资源保存在项目中
  • 矩阵的各种计算:乘法、逆矩阵、转置、行列式等——基于Excel实现
  • 使用ookii-dialogs-wpf在WPF选择文件夹时能输入路径
  • Redis主从复制(replication)
  • react native 环境准备
  • 三极管在数字电路中的应用
  • PyQt6 QToolButton工具按钮控件
  • Nacos源码解读04——服务发现
  • linux 内核regulator
  • 记录 | linux查看文件夹大小
  • 【c++随笔15】c++常用第三方库
  • 浅学指针(5)sizeof和strlen的进阶理解
  • k8s安装步骤
  • Pandas实战:电商平台用户分析
  • 【一个超简单的爬虫demo】探索新浪网:使用 Python 爬虫获取动态网页数据
  • android studio安装SDK时无法勾选
  • 逻辑漏洞测试靶场实验
  • vue $nextTick 样式私有化
  • 设计模式--观察者模式(Observer Pattern)
  • 如何熟练使用vim工具?
  • spring boot的redis连接数过多导致redis服务器压力过大的一次问题排查
  • 数据挖掘之时间序列分析
  • 万界星空科技灯具行业MES介绍
  • 【java毕业设计源码】基于SSM框架的在线智能题库管理系统设计与实现