首页 > 其他分享 >手写Promise

手写Promise

时间:2024-02-17 15:57:37浏览次数:24  
标签:resolve val value task Promise reject 手写

目录

参考资料

Promises 介绍文档

Promises/A+ 规范

Promises 的一种实现方式

github 上 2.6k+ star 的一个 Promise 实现方式

手写 Promise

自己手动实现的简易版 Promise,便于理解 Promise 工作原理。以下实现版本,并未完全 compilant to Promises/A+ 规范,但对于用户理解 Promise 工作原理已有很大帮助。
myPromise.js

let PENDING = 'pending'
let FULFILLED = 'fulfilled'
let REJECTED = 'rejected'


class Promise {
    state
    value
    handlers = []
    constructor(executor) {
        this.state = PENDING
        try {
            executor(this.#resolve.bind(this), this.#reject.bind(this))
        } catch (err) {
            this.#reject(err)
        }
    }

    #resolve(data) {
        this.#changeState(FULFILLED, data)
    }
    #reject(err) {
        this.#changeState(REJECTED, err)
    }

    #changeState(newState, data) {
        // 状态只能改变一次
        if (this.state !== PENDING) return
        this.state = newState
        this.value = data

        // 检查一下是否有 then() 添加的 handler,如果有,就将这些 handler 包装成 task 放入 micro task queue
        this.#runHandlers()
    }

    then(onFulfilled, onRejected) {
        return new Promise((resolve, reject) => {
            this.handlers.push(new Handler(onFulfilled, onRejected, resolve, reject))
            this.#runHandlers()
        })
    }

    /**
     * 
     * 将所有 handler 放入 microt task queue,不会阻塞很长时间
     */
    #runHandlers() {
        if (this.state === PENDING) return
        while (this.handlers.length > 0) {
            const handler = this.handlers.shift()
            runMicroTask(() => {
                const { onFulfilled, onRejected, resolve, reject } = handler
                const onHandler = (this.state === FULFILLED) ? onFulfilled : onRejected
                const resolveOrReject = (this.state === FULFILLED) ? resolve : reject
                if (onHandler) {
                    try {
                        const result = onHandler(this.value)
                        if (isPromise(result)) {
                            result.then(resolve, reject)
                        } else {
                            resolve(result)
                        }
                    } catch (ex) {
                        reject(ex)
                    }
                } else {
                    resolveOrReject(this.value)
                }
            })
        }
    }
}

/**
 * 
 * @param {*} value onFulfilled/onRejected 返回的值
 * @returns true: 是 Promise; false: 不是 Promise
 * @reference 参考 Promises/A+规范:https://promisesaplus.com/
 * @reference 1.1 “promise” is an object or function with a then method whose behavior conforms to this specification.
 */
function isPromise(value) {
    return ((typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function')
}

/**
 * 
 * @param {*} task 将要放入 micro task queue 的任务
 */
function runMicroTask(task) {
    if (typeof process === 'object' && typeof process.nextTick === 'function') {
        process.nextTick(task) // nodejs 环境,将 task 放入 micro task queue
    } else {
        setTimeout(task, 0) // 这里其实将 task 放入了 macro task queue
    }
}

class Handler {
    constructor(onFulfilled, onRejected, resolve, reject) {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
        this.resolve = resolve;
        this.reject = reject;
    }
}

export default Promise;

测试运行

testPromise.js

const Promise = require('./myPromise.js')

let p = new Promise((resolve) => {
    setTimeout(() => {
        resolve(200)
        console.log('timeout, p:', p)
    }, 3000)
})
p.then((val) => {
    console.log('the very first then, value:', val)
})
p.then((val) => {
    console.log('first then, value:', val)
    return new Promise((res, rej) => {
        res(val + 1)
    })
}).then((val) => {
    console.log('second then, value:', val)
    return new Promise((res, rej) => {
        rej(val + 1)
    })
}).then(null, (val) => {
    console.log('third then, rejected, value:', val)
    throw (val + 1)
}).then(null, (val) => {
    console.log('forth then, rejected, value:', val)
    return val + 1
}).then((val) => {
    console.log('fifth then, value:', val)
})

执行结果

$ node testPromise.js 
timeout, p: Promise { state: 'fulfilled', value: 200, handlers: [] }
the very first then, value: 200
first then, value: 200
second then, value: 201
third then, rejected, value: 202
forth then, rejected, value: 203
fifth then, value: 204

标签:resolve,val,value,task,Promise,reject,手写
From: https://www.cnblogs.com/dongling/p/18018039

相关文章

  • 什么是 axios?axios与promise区别
    Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中promise是现代javascript中异步编程的基础,是一个由异步函数返回的可以向我们指示当前操作所处的状态的对象使用cdn:<scriptsrc="https://unpkg.com/axios/dist/axios.min.js"></script>//为给定ID的u......
  • [RxJS] firstValueFrom/lastValueFrom (convert observable to promise)
    Convertsanobservabletoapromisebysubscribingtotheobservable,andreturningapromisethatwillresolveassoonasthefirstvaluearrivesfromtheobservable.Thesubscriptionwillthenbeclosed.WARNING:Onlyusethiswithobservablesyou know ......
  • 手写实现cni插件
    k8sv1.19.0mycni配置文件cat>>/etc/cni/net.d/mycni.json<<EOF{"cniVersion":"0.2.0","name":"mycni","type":"mycni"}EOFtype对应/opt/cni/bin目录下二进制文件。mycni代码并编译mkdir/run/n......
  • pytorch MNIST数据集手写数字识别
    MNIST包括6万张28x28的训练样本,1万张测试样本,很多教程都会对它”下手”几乎成为一个“典范”,可以说它就是计算机视觉里面的HelloWorld。所以我们这里也会使用MNIST来进行实战。importtorchimporttorch.nnasnnimporttorch.nn.functionalasFimporttorch.optimasopt......
  • C++中promise和future初认识
    future/promisefuture提供了一个基于数据(future模板类型)的异步概念:对于一个类型T,可以在以后通过get接口获得这个类型T的变量。或者打个不太恰当的比方,当你获得一个future对象时,就获得了一个消费券(consumer):拿着这张券可以兑换(get)一个T类型的结果(如果数据未就绪的话会阻塞等......
  • 手写docker—资源限制(三)
    简介上一节中我们完成了Mydockerrun-it/bin/sh的方式创建并启动容器。本节我们通过cgroups来实现对容器资源的限制。通过增加-mem、-cpu等命令行参数来限制资源,完整命令比如Mydockerrun-it-mem10m-cpu20/bin/sh。核心需要实现以下逻辑:新增-mem、-cpu命令行......
  • Promise, async, await实现异步编程,代码详解
    写在开头一点题外话其实最近在不断的更新Java的知识,从基础到进阶,以及计算机基础、网络、WEB、数据库、数据结构、Linux、分布式等等内容,预期写成一个既可以学习提升又可以面试找工作的《Java成长之路》!算是对自己学习的总结(笔记),也算是一种程序猿的记忆,现在大环境那么差,万一哪天......
  • 延迟Promise/单项目多npm版本/webpack好处/webpack5构建速度
    《Promise.withResolvers延迟Promise》https://sorrycc.com/promise-with-resolvers/promise当被reject之后,再次resolve,都是会返回reject的消息一个npm包的多个版本webpack好处需要通过模块化的方式来开发使用一些高级的特性来加快我们的开发效率或者安全性,比如通过ES6......
  • flat 拍平数组 手写flat拍平数组
    //flat拍平一维数组letflaoatArr=[1,3,5,6,3,6,[3,46,465,3]]letres=flat(flaoatArr)console.log(res);letres=flaoatArr.flat()console.log(res);//手写float数组Array.protot......
  • 手写docker—构造容器(二)
    Dockerrun命令实现本文需要实现第一个命令Mydockerrun,类似于dockerrun-it[command]命令。通过创建新的Namespace来对新进程进行视图隔离。核心需要解决如下问题:命令行参数解析的问题,具体实现时通过github.com/urfave/cli库来实现对用户输入命令行的解析,需要解析......