惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LangChain Blog
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
Last Week in AI
Last Week in AI
P
Privacy International News Feed
C
CERT Recently Published Vulnerability Notes
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
Y
Y Combinator Blog
月光博客
月光博客
博客园 - Franky
T
Threatpost
Security Latest
Security Latest
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
T
The Exploit Database - CXSecurity.com
A
About on SuperTechFans
I
Intezer
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
Cisco Blogs
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Security Blog
Microsoft Security Blog
Know Your Adversary
Know Your Adversary
IT之家
IT之家
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
NISL@THU
NISL@THU
博客园 - 三生石上(FineUI控件)
L
Lohrmann on Cybersecurity
小众软件
小众软件
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta

博客园 - HorseShoe2016

Ethereum 学习笔记 ---- Solidity 数据位置(Calldata, Memory, Storage)编码与布局全解析 vscode 禁用警告提示音 浏览器加载 HTML 页面并执行 Javascript 的流程图 Ethereum学习笔记 ---- 多重继承中的 C3线性化算法 Ethereum学习笔记 ---- 使用 Remix 调试功能理解 bytes 在 memory 中的布局 Ethereum学习笔记 ---- 通过 Event 学习《合约ABI规范》 Javascript: Blob, File/FileReader, ArrayBuffer, ReadableStream, Response 转换方法 vscode 无法调试 golang testify suite 中的单个 test 的解决办法 纯js实现 vue 组件 与 vue 单文件组件对比 一个简单的 indexedDB 应用示例 html 元素的 onEvent 与 addEventListener vue3 defineComponent: 使用纯 Javascript 定义组件 vue3 动态编译组件失败:Component provided template option but runtime compilation is not supported in this build of Vue Javascript Object 中,isExtensible/isSealed/isFrozen 的对比 mini-vue: 响应式数据的实现 vscode vue 插件与 emmet、tailwind css 插件冲突的解决方案 Python 安装依赖包,出现 ssl.SSLCertVerificationError 的问题,解决方法 CentOS7 源码编译安装 Python 3.8.10,开启 SSL 功能 Protocol Buffer Go (proto3) - macos 搭建 protocol buffer 环境 + Encoding 实验
手写Promise
HorseShoe2016 · 2024-02-17 · via 博客园 - HorseShoe2016

参考资料

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 放入 micro task queue,不会阻塞很长时间
     */
    #runHandlers() {
        if (this.state === PENDING) return
        while (this.handlers.length > 0) {
            const handler = this.handlers.shift()
            queueMicrotask(() => {
                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')
}


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

posted on 2024-02-17 15:33  HorseShoe2016  阅读(52)  评论()    收藏  举报