手写 Promise(2)实例方法与静态方法的实现

news2024/9/26 3:24:06

一:什么是 Promise

        Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。    

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

二:手写Promise

1、实例方法(catch、finally)

设计思路

内部调用then

处理异常

代码实现

<body>
    <script>
        // 定义函数
        function runAsynctask(callback) {// callback 是一个回调函数
            // 调用核心api
            if (typeof queueMicrotask === 'function') { // 调用三个函数是为了解决浏览器不兼容问题,先判断是不是函数
                queueMicrotask(callback)
            } else if (typeof MutationObserver === "function") {
                const obs = new MutationObserver(callback)
                const divNode = document.createElement('div')
                obs.observe(divNode, { childList: true })
                divNode.innerHTML = '打酱油改变以下内容'
            } else {
                setTimeout(callback, 0)
            }
        }

        const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'
        class wePromise {
            state = PENDING // 状态
            result = undefined // 原因
            #handlers = [] // [{onFulfilled,onReject},......]
            // 构造函数
            constructor(func) {
                // 改状态,pending => fulfilled
                const reslove = (result) => {
                    if (this.state === PENDING) {
                        this.state = FULFILLED
                        this.result = result
                        // 下面这个是异步的时候,先保存,然后到这一步执行,就取出保存的函数并且执行
                        this.#handlers.forEach(({ onFulfilled }) => { // 解构
                            onFulfilled(this.result)
                        })
                    }
                }
                // 改状态,pending => rejected
                const reject = (result) => {
                    if (this.state === PENDING) {
                        this.state = REJECTED
                        this.result = result
                        this.#handlers.forEach(({ onReject }) => {
                            onReject(this.result)
                        })
                    }
                }

                // 异常的处理
                try {
                    // 执行回调函数
                    func(reslove, reject)
                } catch (error) {
                    reject(error)
                }
            }

            then(onFulfilled, onReject) {
                // 判断传入的参数是不是函数
                onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
                onReject = typeof onReject === 'function' ? onReject : x => { throw x }

                const p2 = new wePromise((reslove, reject) => {
                    // 判断执行完成后的状态
                    if (this.state === FULFILLED) {
                        runAsynctask(() => {
                            try {
                                // 获取返回值
                                const x = onFulfilled(this.result) // 返回结果
                                reslovePromise(p2, x, reslove, reject)
                            } catch (error) {
                                // 处理异常
                                reject(error)
                            }

                        })
                    } else if (this.state === REJECTED) {
                        runAsynctask(() => {
                            try {
                                const x = onReject(this.result)
                                reslovePromise(p2, x, reslove, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    } else if (this.state === PENDING) { // 还没有改变状态,说明是异步
                        // 保存回调函数
                        this.#handlers.push({
                            onFulfilled: () => {
                                runAsynctask(() => {
                                    try {
                                        const x = onFulfilled(this.result) // 返回结果
                                        reslovePromise(p2, x, reslove, reject)
                                    } catch (error) {
                                        reject(error)
                                    }
                                })
                            },
                            onReject: () => {
                                runAsynctask(() => {
                                    try {
                                        const x = onReject(this.result) // 返回结果
                                        reslovePromise(p2, x, reslove, reject)
                                    } catch (error) {
                                        reject(error)
                                    }
                                })
                            }
                        })
                    }
                })


                return p2
            }
            catch(onReject) {
                // 内部调用then方法
                return this.then(undefined, onReject)
            }
            finally(onFinally){
                return this.then(onFinally,onFinally)
            }
        }

        function reslovePromise(p2, x, reslove, reject) {
            // 处理重复引用
            if (x === p2) {
                // 抛出错误
                throw new TypeError('Chaining cycle detected for promise #<Promise>')
            }
            // 处理返回的Promise
            if (x instanceof wePromise) {
                // 调用then方法
                x.then(res => reslove(res), err => reject(err))
            } else {
                // 处理返回值
                reslove(x)
            }
        }
        // 创建对象,调用两个方法
        const p = new wePromise((reslove, reject) => {
            // reslove('success')
            // reject('reject')
            throw 'throw-error'
        })
        p.then(res => {
            console.log('成功回调1:', res);
            // throw 'throw-error'
            // return 2
        }).catch(err => {
            console.log('失败回调1:', err);

        }).finally(() => {
            console.log('finally');
        })
    </script>
</body>

运行效果

2、静态方法(reslove、reject、race)

reslove、reject设计思路

  • 判断传入值
  • Promise返回
  • 转换为Promise返回

 race设计思路

  •  返回Promise
  • 判断是否为数组
  • 等待第一个敲定

all设计思路

  • 返回Promise
  • 判断是否为数组
  • 空数组直接兑换
  • 处理全部兑换(记录结果 --> 判断全部兑现)
  • 处理第一个拒绝 

allSettled设计思路

  • 返回Promise
  • 判断是否为数组
  • 空数组直接兑换
  • 等待全部敲定(记录结果 --> 处理兑换 或 拒绝)

any设计思路

  • 返回Promise
  • 判断是否为数组
  • 空数组直接拒绝
  • 等待结果(第一个兑现,全部拒绝)

代码实现

<body>
    <script>
        // 定义函数
        function runAsynctask(callback) {// callback 是一个回调函数
            // 调用核心api
            if (typeof queueMicrotask === 'function') { // 调用三个函数是为了解决浏览器不兼容问题,先判断是不是函数
                queueMicrotask(callback)
            } else if (typeof MutationObserver === "function") {
                const obs = new MutationObserver(callback)
                const divNode = document.createElement('div')
                obs.observe(divNode, { childList: true })
                divNode.innerHTML = '打酱油改变以下内容'
            } else {
                setTimeout(callback, 0)
            }
        }

        const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'
        class wePromise {
            state = PENDING // 状态
            result = undefined // 原因
            #handlers = [] // [{onFulfilled,onReject},......]
            // 构造函数
            constructor(func) {
                // 改状态,pending => fulfilled
                const reslove = (result) => {
                    if (this.state === PENDING) {
                        this.state = FULFILLED
                        this.result = result
                        // 下面这个是异步的时候,先保存,然后到这一步执行,就取出保存的函数并且执行
                        this.#handlers.forEach(({ onFulfilled }) => { // 解构
                            onFulfilled(this.result)
                        })
                    }
                }
                // 改状态,pending => rejected
                const reject = (result) => {
                    if (this.state === PENDING) {
                        this.state = REJECTED
                        this.result = result
                        this.#handlers.forEach(({ onReject }) => {
                            onReject(this.result)
                        })
                    }
                }

                // 异常的处理
                try {
                    // 执行回调函数
                    func(reslove, reject)
                } catch (error) {
                    reject(error)
                }
            }

            then(onFulfilled, onReject) {
                // 判断传入的参数是不是函数
                onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
                onReject = typeof onReject === 'function' ? onReject : x => { throw x }

                const p2 = new wePromise((reslove, reject) => {
                    // 判断执行完成后的状态
                    if (this.state === FULFILLED) {
                        runAsynctask(() => {
                            try {
                                // 获取返回值
                                const x = onFulfilled(this.result) // 返回结果
                                reslovePromise(p2, x, reslove, reject)
                            } catch (error) {
                                // 处理异常
                                reject(error)
                            }

                        })
                    } else if (this.state === REJECTED) {
                        runAsynctask(() => {
                            try {
                                const x = onReject(this.result)
                                reslovePromise(p2, x, reslove, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    } else if (this.state === PENDING) { // 还没有改变状态,说明是异步
                        // 保存回调函数
                        this.#handlers.push({
                            onFulfilled: () => {
                                runAsynctask(() => {
                                    try {
                                        const x = onFulfilled(this.result) // 返回结果
                                        reslovePromise(p2, x, reslove, reject)
                                    } catch (error) {
                                        reject(error)
                                    }
                                })
                            },
                            onReject: () => {
                                runAsynctask(() => {
                                    try {
                                        const x = onReject(this.result) // 返回结果
                                        reslovePromise(p2, x, reslove, reject)
                                    } catch (error) {
                                        reject(error)
                                    }
                                })
                            }
                        })
                    }
                })


                return p2
            }

            // 实例方法
            catch(onReject) {
                // 内部调用then方法
                return this.then(undefined, onReject)
            }
            finally(onFinally) {
                return this.then(onFinally, onFinally)
            }

            // 静态方法
            static reslove(value) {
                // 判断传入的是不是Promise对象
                if (value instanceof wePromise) {
                    return value
                }
                return new wePromise((reslove, reject) => {
                    reslove(value)
                })

            }
            static reject(value) {
                return new wePromise((reslove, reject) => {
                    reject(value)
                })
            }
            static race(promises) {
                return new wePromise((reslove, reject) => {
                    // 判断是否为数组
                    if (!Array.isArray(promises)) {
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 等待第一个敲定
                    promises.forEach(p => {
                        wePromise.reslove(p).then(res => { reslove(res) }, err => { reject(err) })
                    })
                })
            }
            // 重要
            static all(promises) {
                // 返回Promise实例
                return new wePromise((reslove, reject) => {
                    // 判断是否为数组
                    if (!Array.isArray(promises)) {
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 空数组直接兑换
                    promises.length === 0 && reslove(promises)
                    // 处理全部兑现
                    const results = []
                    let count = 0
                    promises.forEach((p, index) => {
                        wePromise.reslove(p).then(res => {
                            results[index] = res
                            count++
                            // 判断全部兑现
                            count === promises.length && reslove(results)
                        }, err => {
                            // 处理第一个拒绝
                            reject(err)
                        })
                    })
                })
            }
            static allSettled(promises) {
                // 返回Promise实例
                return new wePromise((reslove, reject) => {
                    // 判断是否为数组
                    if (!Array.isArray(promises)) {
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 空数组直接兑换
                    promises.length === 0 && reslove(promises)
                    // 等待全部敲定
                    const results = []
                    let count = 0
                    promises.forEach(p => {
                        // 之所以是使用这个静态方法,是因为这个将传入的对象包装成了wePromise
                        wePromise.reslove(p).then((res => {
                            // 处理兑现
                            results[index] = { status: FULFILLED, value: res }
                            count++
                            count === promises.length && reslove(results)
                        }, err => {
                            results[index] = { status: REJECTED, reason: err }
                            count++
                            count === promises.length && reslove(results)
                        }))
                    })

                })
            }
            static any(promises) {
                return new wePromise((reslove, reject) => {
                    // 判断是否为数组
                    if (!Array.isArray(promises)) {
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 空数组直接拒绝
                    promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))

                    // 等待结果
                    const errors = []
                    let count = 0
                    promises.forEach((p, index) => {
                        wePromise.reslove(p).then(res => {
                            // 第一个兑现
                            reslove(res)
                        }, err => {
                            // 全部拒绝
                            errors === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
                        })
                    })


                })
            }

        }

        function reslovePromise(p2, x, reslove, reject) {
            // 处理重复引用
            if (x === p2) {
                // 抛出错误
                throw new TypeError('Chaining cycle detected for promise #<Promise>')
            }
            // 处理返回的Promise
            if (x instanceof wePromise) {
                // 调用then方法
                x.then(res => reslove(res), err => reject(err))
            } else {
                // 处理返回值
                reslove(x)
            }
        }
        // 创建对象,调用两个方法
        const p = new wePromise((reslove, reject) => {
            // reslove('success')
            // reject('reject')
            throw 'throw-error'
        })
        p.then(res => {
            console.log('成功回调1:', res);
            // throw 'throw-error'
            // return 2
        }).catch(err => {
            console.log('失败回调1:', err);

        }).finally(() => {
            console.log('finally');
        })
    </script>
</body>

运行效果

        这里运行效果请复制代码自己测,实例方法和静态方法已经是全部实现了的。

三:总结

        Promise 是异步编程的一种解决方案,其在工作的项目开发中是非常常用的,熟练的掌握Promise 的内容,熟悉底层源码,可以让我们在项目开发中具备更高超的代码书写能力,同时降低自己在使用Promise 出现的各种bug。好啦,Promise 源码系列到此就算是结束啦,希望能够对各位小伙伴有所帮助哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[③ADRV902x]: Digital Filter Configuration(接收端)

前言 本篇博客主要总结了ADRV9029 Rx接收端链路中各个滤波器的配置。配置不同的滤波器系数以及不同的参数&#xff0c;可以对输入的数字信号灵活得做decimation处理&#xff0c;decimation信号抽取&#xff0c;就是降低信号采样率的过程。 Receiver Signal Path 下图为接收端…

macbook2024免费mac系统优化清理软件CleanMyMac X

清理电脑的操作系统可能是我们一直以来的习惯&#xff0c;从windows系统到mac系统&#xff0c;我们一直在寻求最好的清理方法&#xff0c;能够有效地清理操作系统对于电脑来说是非常重要的。今天小编想和大家一起讨论使用在macbook上的清理软件&#xff0c;清理macbook的空间可…

在React中,什么是状态(state)?如何更新组件的状态?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

C语言程序设计——输入三个整数x,y,z,请把这三个数由小到大输出

题目&#xff1a;输入三个整数x,y,z&#xff0c;请把这三个数由小到大输出。 程序分析&#xff1a;我们想办法把最小的数放到x上&#xff0c;先将x与y进行比较&#xff0c; 如果x>y则将x与y的值进行交换&#xff0c;然后再用x与z进行比较&#xff0c;如果x>z则将x与z的值…

谈谈Net-SNMP软件

Net-SNMP是一个开源的SNMP软件套件&#xff0c;它提供了SNMP代理&#xff08;snmpd&#xff09;和SNMP工具&#xff08;如snmpget、snmpwalk等&#xff09;&#xff0c;可以用于监控和管理网络设备。 Net-SNMP最初是从UC Davis的SNMP软件衍生而来&#xff0c;现在已经成为广泛…

SpringAOP源码解析之advice构建排序(二)

上一章我们知道Spring开启AOP之后会注册AnnotationAwareAspectJAutoProxyCreator类的定义信息&#xff0c;所以在属性注入之后initializeBean的applyBeanPostProcessorsAfterInitialization方法执行的时候调用AnnotationAwareAspectJAutoProxyCreator父类(AbstractAutoProxyCre…

通过怪物展示Demo理解游戏设计模式中的迭代器模式

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 今天我们要来聊一聊游戏…

开启生成式AI的探索之旅,亚马逊云科技分享生成式AI热门案例

现今&#xff0c;生成式AI为企业争先讨论的热门话题&#xff0c;上云出海为企业转型的重中之重。无论你是行业新贵还是中小企业&#xff0c;探索新的模式、创新迭代业务都是不容忽视的重点&#xff0c;下面就来介绍几个亚马逊云科技帮助企业创新的案例。 开启生成式AI的探索之旅…

深入理解 MySQL 中的锁和MVCC机制

文章目录 锁&#xff1a;数据访问的保护者1. 了解锁的基本概念2. 锁的使用场景3. 示例&#xff1a;MySQL中的锁 MVCC&#xff1a;多版本并发控制1. MVCC的工作原理2. MVCC的优点3. 示例&#xff1a;MySQL中的MVCC 如何选择合适的锁和MVCC1. 确定隔离级别2. 避免过度使用锁3. 监…

Spring IOC 和 AOP

核心概念 咱们这节就讲完了&#xff0c;在这节中我们讲了两个大概念&#xff0c;一个叫做IOC&#xff0c;一个叫做DI IOC是什么&#xff1f;是用对象的时候不要自己用new而是由外部提供&#xff0c;而spring在进行实现的时候是谁提供&#xff0c;就是IOC容器给你提供。 DI是什…

什么是脚本文件,脚本的执行,脚本格式等

1.脚本文件是什么&#xff1f; 脚本文件是包含一系列计算机命令的文本文件&#xff0c;通常用于自动化任务、自定义功能或执行特定操作。这些命令通常按照一定的编程语法和语义规则编写&#xff0c;以便计算机能够逐行解释和执行它们。脚本文件通常包含了一组操作&#xff0c;…

lua-web-utils和proxy设置示例

以下是一个使用lua-web-utils和proxy的下载器程序&#xff1a; -- 首先安装lua-web-utils库 local lwu require "lwu" ​ -- 获取服务器 local function get_proxy()local proxy_url "duoipget_proxy"local resp, code, headers, err lwu.fetch(proxy_…

工业通信网关常用的工业通信协议

在工业领域中常常有不同的设备协同工作&#xff0c;而这些设备的通信协议和数据格式也有所差异&#xff0c;要想实现不同通信设备之间的数据传输互通&#xff0c;工业网关是一个重要的设备。 什么是工业网关 工业网关是一种能够连接多种不同设备并实现数据的收集、传输、处理和…

Vuepress 三分钟搭建一个精美的文档或博客

大家好&#xff0c;我是凌览。 作为一个程序员&#xff0c;相信每个人都想折腾一个属于自己的博客。技术文章的输出是我们程序员能力的一种体现&#xff0c;也是一种非常好的个人总结。 网上有很多文档编写网站及工具&#xff0c;比如语雀、石墨等等。但多数需要付费&#xf…

工业RFID设备如何实现抗干扰功能?

在工业环境中存在多种干扰因素&#xff0c;如灰尘、水渍、油污等都会影响条码枪的信息识别&#xff0c;虽然RFID技术可以实现非接触的识别&#xff0c;无视油污、灰尘等环境&#xff0c;但仍会收到电流、震动、电磁信号等因素的干扰。下面我们就一起来了解一下&#xff0c;工业…

触摸屏与施耐德PLC之间MODBUS无线通讯

一、 硬件连接 1、PLC通讯接口说明&#xff1a; 2、通讯电缆图&#xff1a; 二、PLC设置 1. 配置端口&#xff1a; 双击串行线路—弹出右侧设置窗口---设置串口通讯参数 2. 添加MODBUS协议。 ① 右击串口线路&#xff0c;选择添加设备&#xff1a; ② 选择现场总线&#xf…

JAVA代码审计-纵向越权漏洞分析

查看这个cms系统后台管理员 添加用户的页面 点击添加管理员 这个模块只有管理员拥有&#xff0c;普通用户没有这个模块。 打开源码分析是否存在越权漏洞。 ------------------------------------------------------------------------------------------------------------ …

引领位置服务驱动:腾讯地图 WebService 服务端 API 实用指南

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…