手写Promise

手写Promise

第一步:实现构造函数(构造器的实现)

第二步:实现then方法

then方法要解决两个问题

第一个问题:then函数的两个参数onFulfilled和onRejected何时执行(then的回调执行时机)

第二个问题:then中返回的Promise什么时候成功,什么时候失败(then的返回值)

处理then的返回值,要分三种情况:

  1. 对应的回调不是函数(穿透),直接resolve或者reject,是resolve还是reject取决于当前的状态
  2. 回调是函数,执行过程如果没有报错,拿到返回值调用resolve,如果报错了,调用reject,支持链式调用
  3. 回调函数的返回结果是一个Promise,则调用它的then方法,将resolve与reject传入

最后需要注意的是要实现一个微队列(因为then的回调是放到微队列里的),需要区分node环境和浏览器环境

还需要实现一个是否是Promise的判断,只要满足Promise A+规范就是Promise,Promise之间具有互操作性

javascript 复制代码
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    #state = 'pending';
    #result = undefined;
    #handler = [];

    constructor(executor) {
        const resolve = (data) => {
            this.#changeState(FULFILLED, data);
        };
        const reject = (reason) => {
            this.#changeState(REJECTED, reason);
        };
        try {
            executor(resolve, reject);
        } catch (reason) {
            this.#changeState(REJECTED, reason);
        }
    }

    #changeState(state, result) {
        if (this.#state !== PENDING) {
            return;
        }
        this.#state = state;
        this.#result = result;
        this.#run();
    }

    #isPromiseLike(value) {
        if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
            return typeof value.then === 'function';
        }
        return false;
    }

    #runMicroTask(func) {
        if (typeof process === 'object' && typeof process.nextTick === 'function') {
            process.nextTick(func);
        } else if (typeof MutationObserver === 'function') {
            const observer = new MutationObserver(func);
            const textNode = document.createTextNode('1');
            observer.observe(textNode, {characterData: true});
            textNode.data = '2';
        } else {
            setTimeout(func, 0);
        }
    }

    #runOne(callback, resolve, reject) {
        this.#runMicroTask(() => {
            if (typeof callback === 'function') {
                try {
                    const data = callback(this.#result);
                    if (this.#isPromiseLike(data)) {
                        data.then(resolve, reject);
                    } else {
                        resolve(data);
                    }
                } catch (err) {
                    reject(err);
                }
            } else {
                const settled = this.#state === FULFILLED ? resolve : reject;
                settled(this.#result);
            }
        })
    }

    #run() {
        if (this.#state === PENDING) {
            return;
        }

        while (this.#handler.length) {
            const {onFulfilled, onRejected, resolve, reject} = this.#handler.shift();
            if (this.#state === FULFILLED) {
                this.#runOne(onFulfilled, resolve, reject);
            } else {
                this.#runOne(onRejected, resolve, reject);
            }
        }
    }

    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            this.#handler.push({
                onFulfilled,
                onRejected,
                resolve,
                reject,
            });
            this.#run();
        })
    }
}

const p = new MyPromise((resolve, reject) => {
    resolve(2);
});

p.then(data => {
    console.log(data)
})

setTimeout(() => {
    console.log(1);
}, 0);

console.log(3);

// 输出3 -> 2 -> 1

设计模式上Promise的实现依托观察者模式。观察内部状态#state的变化触发then函数中的回调函数。

相关推荐
是苏浙3 小时前
Java实现链表1
java·开发语言
磊 子3 小时前
C++设计模式
javascript·c++·设计模式
Jinkxs3 小时前
Rust 性能优化全流程:从 flamegraph 定位瓶颈到 unsafe 与 SIMD 加速,响应快 2 倍
开发语言·性能优化·rust
尘中远3 小时前
Qt高性能绘图库QIm——实现二维三维科学绘图
开发语言·qt·信息可视化
雨辰AI3 小时前
从零搭建大模型本地运行环境|Python+CUDA 基础配置避坑大全
大数据·开发语言·人工智能·python·ai·ai编程·ai写作
DogDaoDao3 小时前
【第 05 篇】Python的字典与集合
开发语言·python·集合·字典
兰令水4 小时前
leecodecode【单调栈】【2026.6.12打卡-java版本】
java·开发语言·算法
leagsoft_10034 小时前
零信任选型五刀法——零信任怎么选?五个问题,五条红线
开发语言·php
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?
java·开发语言·面试
IT WorryFree4 小时前
Zabbix 7.4 API 可同步全量参数清单(同步第三方系统专用)
java·开发语言·zabbix