promise源码实现

news/2024/7/19 15:42:58 标签: js
js">class Promise {
	// 三状态:等待态、成功态、失败态
    static PENDING = 'pending'
    static RESOLVED = 'resolved'
    static REJECTED = 'rejected'
    constructor(excutor) {
    	// promise实例初始化
        this.state = Promise.PENDING // 默认为等待态
        this.value = undefined	// then方法成功回调函数的参数
        this.reason = undefined // then方法失败回调函数的参数
        this.resolveCallbacks = [] // 成功态回调队列
        this.rejectCallbacks = [] // 失败态回调队列
        // 定义成功态执行函数
        let resolve = (value) => {
        	// 只能从等待态改为成功态,状态改变后,不再改变
            if (this.state === Promise.PENDING) {
                this.state = Promise.RESOLVED
                this.value = value
                // 清空成功态回调队列
                this.resolveCallbacks.forEach(fn => fn())
            }
        }
        // 定义失败态执行函数
        let reject = (reason) => {
        	// 只能从等待态改为失败态,状态改变后,不再改变
            if (this.state === Promise.PENDING) {
                this.state = Promise.REJECTED
                this.reason = reason
                // 清空失败态回调队列
                this.rejectCallbacks.forEach(fn => fn())
            }
        }
        try {
        	// 执行构造函数回调
            excutor(resolve, reject)
        } catch (e) {
        	// 执行出错,则为失败态
            reject(e)
        }
    }
    then(onResolved, onRejected) {
    	// onResolved:成功态的回调函数
    	// onRejected:失败态的回调函数
    	// 如果onResolved和onRejected不是函数,那么就需要强制转换成函数
        onResolved = typeof onResolved === 'function' ? onResolved : val => val
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
        //promise实例调用then方法都会返回一个新的promise实例
        return new Promise((resolve, reject) => {
            if (this.state === Promise.RESOLVED) {
            	// 成功态调用onResolved回调函数
            	// 用setTimeout模拟异步执行
                setTimeout(() => {
                    try {
                        const res = onResolved(this.value)
                        // 如果回调函数的返回值是一个promise实例,那么就执行该promise实例的then方法,并将resolve和reject作为该promise实例的成功回调和失败回调,递归执行直到该promise实例状态确定为止
                        if (res instanceof Promise) {
                            res.then(resolve, reject)
                        } else {
                        	//否则,就将这个值作为新的promise实例成功态的参数
                            resolve(res)
                        }
                    } catch (e) {
                    	// 回调函数执行出错,就将这个值作为新的promise实例失败态的参数
                        reject(e)
                    }
                });
            } else if (this.state === Promise.REJECTED) {
            	// 成功态调用onRejected回调函数
                setTimeout(() => {
                    try {
                        const res = onRejected(this.reason)
                        if (res instanceof Promise) {
                            res.then(resolve, reject)
                        } else {
                            resolve(res)
                        }
                    } catch (e) {
                        reject(e)
                    }
                });
            } else if (this.state === Promise.PENDING) {
            	// 如果当前是等待态,那么就将成功的回调和失败的回调分别加入成功回调队列和失败回调队列;
            	// 当状态改变为非等待态时,依次执行对应状态回调队列中的回调函数
                this.resolveCallbacks.push(() => {
                    try {
                        const res = onResolved(this.value)
                        if (res instanceof Promise) {
                            res.then(resolve, reject)
                        } else {
                            resolve(res)
                        }
                    } catch (e) {
                        reject(e)
                    }
                })
                this.rejectCallbacks.push(() => {
                    try {
                        const res = onRejected(this.reason)
                        if (res instanceof Promise) {
                            res.then(resolve, reject)
                        } else {
                            resolve(res)
                        }
                    } catch (e) {
                        reject(e)
                    }
                })
            }
        })
    }
    // 静态函数
    static resolve(promise) {
        return new Promise((resolve, reject) => {
            if (promise instanceof Promise) {
                promise.then(resolve, reject)
            } else {
                resolve(promise)
            }
        })
    }
    static reject(promise) {
        return new Promise((resolve, reject) => {
            reject(promise)
        })
    }
    static all(promises) {
        return new Promise((resolve, reject) => {
            let arr = []
            let cnt = 0

            function processData(index, value) {
                arr[index] = value
                if (++cnt === promises.length) {
                    resolve(arr)
                }
            }
            promises.forEach((p, index) => {
                Promise.resolve(p).then(res => {
                    processData(index, res)
                }, reject)
            })
        })
    }
    static race(promises) {
        return new Promise((resolve, reject) => {
            promises.forEach((p) => {
                Promise.resolve(p).then(resolve, reject)
            })
        })
    }
}
module.exports = Promise

http://www.niftyadmin.cn/n/620610.html

相关文章

css实现switch开关状态切换

1 图标效果 2 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdev…

文字溢出自动向上循环滚动

1 效果展示 2 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice…

公告栏文本横向循环滚动

1 效果展示 2 动画实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthde…

axios数组传参之后端无法解析

问题&#xff1a;现有一个post请求&#xff0c;需要把一个对象数组数据传给后端&#xff0c;如果直接把对象数组传给后端&#xff0c;发现后端接收后的值为[Object, Object]&#xff0c;后端无法解析。解决方案&#xff1a;再发送请求之前&#xff0c;先把该对象数组转化成json…

Vue原型上自定义属性类型检查配置,提升vscode项目开发效率

1 体验效果 1.1 配置前 按住Ctrl键&#xff0c;用鼠标左键点击挂载在Vue原型上的自定义属性时&#xff0c;无法自动跳转到该属性定义的对应位置&#xff0c;只能通过全局搜索查找&#xff0c;效率低下。 1.2 配置后 按住Ctrl键&#xff0c;用鼠标左键点击挂载在Vue原型上的自定…

html页面刷新或关闭前的操作

页面会触发beforeunload或者pagehide事件 1 代码实现 const listenerCallbacks new Set() const listenerCenter {add (listener) {listenerCallbacks.add(listener)},remove (listener) {listenerCallbacks.delete(listener)} } function onBeforeClose () {for (let liste…

webview使用uni.chooseImage从相册返回不触发回调的优化处理

1 问题与方案 问题&#xff1a;在webview上使用uni.chooseImage进入手机系统相册&#xff0c;不选择图片而是直接通过手机系统返回键返回webviiew页面时&#xff0c;不会触发uni.chooseImage的回调&#xff0c;假如在选择图片之前做了防重&#xff0c;那么此时就没法取消防重&a…

java球体旋转3d效果_CSS环绕球体的旋转文字-3D效果

项目文件结构截图只需要一个html文件既可&#xff1a;项目截图&#xff1a;代码实现原理&#xff1a;该示例的实现过程很简单&#xff0c;主要是使用了CSS3的透视、3D旋转、位移、渐变、阴影&#xff0c;可以说是一次比较全面的练习。HTML部分&#xff1a;这里是文字CSS部分&am…