promise源码解析

一、定义promise类

promise主要用于处理异步操作的方法,它可以用于避免回调地狱的问题,它在事件循环中属于异步任务中的微任务,.then后面的内容。

promise有三种状态,pending,fulfilled,rejected,可以由pending转化成其他的两个状态而不能返回原来的状态。当promise的构造器执行resolve的回调时候,pending的状态会变成fulfilled,当构造器执行rejected的回调时候,pending的状态会变成rejected

ini 复制代码
// 定义 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    constructor(executor) {
        // 初始化状态为 pending
        this.status = PENDING;
        // 存储成功的值
        this.value = undefined;
        // 存储失败的原因
        this.reason = undefined;
        // 存储成功的回调函数
        this.onFulfilledCallbacks = [];
        // 存储失败的回调函数
        this.onRejectedCallbacks = [];

        // 成功的处理函数
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
                // 执行所有成功的回调函数
                this.onFulfilledCallbacks.forEach(callback => callback());
            }
        };

        // 失败的处理函数
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
                // 执行所有失败的回调函数
                this.onRejectedCallbacks.forEach(callback => callback());
            }
        };

二、then方法

.then方法,该方法是对回调函数进行处理,当状态是fulfilled的时候,会执行成功的回调,当状态是rejected的时候执行失败的回调,

  • 需要判定onFulfilled是否是个函数,如果不是函数则直接返回相应的值,
  • 后面判定的操作是加入异步的方式,只有加上settimeout的方式才能实现promise的异步操作。
  • 一定要有pending值的状态判定,否则当宏任务中套微任务时候,就无法正确输出成功的回调,当状态是pending的时候,需要将成功或者失败的回调函数存储起来,
  • 在执行then函数的时候需要定义一个新的promise函数,这是由于为了实现链式的调用,
javascript 复制代码
then(onFulfilled, onRejected) {
        // 处理 onFulfilled 不是函数的情况
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        // 处理 onRejected 不是函数的情况
        onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };

        const newPromise = new MyPromise((resolve, reject) => {
            const handleFulfilled = () => {
                try {
                    const result = onFulfilled(this.value);
                    // 如果 result 是一个 Promise 实例
                    if (result instanceof MyPromise) {
                        result.then(resolve, reject);
                    } else {
                        // 否则直接将结果传递给新 Promise 的 resolve 方法
                        resolve(result);
                    }
                } catch (error) {
                    // 如果执行出错,调用新 Promise 的 reject 方法
                    reject(error);
                }
            };

            const handleRejected = () => {
                try {
                    const result = onRejected(this.reason);
                    if (result instanceof MyPromise) {
                        result.then(resolve, reject);
                    } else {
                        resolve(result);
                    }
                } catch (error) {
                    reject(error);
                }
            };

            if (this.status === FULFILLED) {
                // 如果状态已经是 fulfilled,立即执行成功的回调函数
                setTimeout(handleFulfilled, 0);
            } else if (this.status === REJECTED) {
                // 如果状态已经是 rejected,立即执行失败的回调函数
                setTimeout(handleRejected, 0);
            } else {
                // 如果状态还是 pending,将回调函数存储起来
                this.onFulfilledCallbacks.push(() => setTimeout(handleFulfilled, 0));
                this.onRejectedCallbacks.push(() => setTimeout(handleRejected, 0));
            }
        });

        return newPromise;
    }

三、静态方法

promise的静态方法为了处理多个promise对象,

  • all:接收一个 Promise 数组,当所有 Promise 都成功时,返回一个包含所有结果的 Promise;只要有一个 Promise 失败,就返回该失败的 Promise。
  • race:接收一个 Promise 数组,只要有一个 Promise 完成(成功或失败),就返回该 Promise 的结果。
ini 复制代码
 static all(promises) {
        return new MyPromise((resolve, reject) => {
            const results = [];
            let completedCount = 0;

            if (promises.length === 0) {
                resolve(results);
                return;
            }

            promises.forEach((promise, index) => {
                MyPromise.resolve(promise).then(
                    value => {
                        results[index] = value;
                        completedCount++;
                        if (completedCount === promises.length) {
                            resolve(results);
                        }
                    },
                    reason => {
                        reject(reason);
                    }
                );
            });
        });
    }

    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach(promise => {
                MyPromise.resolve(promise).then(
                    value => {
                        resolve(value);
                    },
                    reason => {
                        reject(reason);
                    }
                );
            });
        });
    }
}
相关推荐
变与不变8066 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半6 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck6 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.6 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子6 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常6 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常6 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋7 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发8 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
屏什么录8 小时前
录屏超过两小时就卡顿崩盘?从参数调优到代码实现,一文彻底搞定长时间录屏
前端·音视频开发