在 JavaScript 中创建您自己的 Promise

在 javascript 中创建您自己的 promise

深入JavaScript Promise:异步回调机制详解及自定义Promise实现

本文将带您深入了解JavaScript Promise的异步回调机制,并指导您亲自动手创建一个符合Promise/A+规范的Promise类。我们将重点关注Promise/A+规范中关键的规则,构建一个简化但功能完备的Promise实现。

一、核心概念

Promise: 一个带有then方法的对象或函数,其行为符合Promise/A+规范。

立即学习“Java免费学习笔记(深入)”;

Thenable: 定义了then方法的对象或函数。

Value: 任何有效的JavaScript值(包括undefined、Thenable或Promise)。

异常 (Exception): 使用throw语句抛出的值。

Reason: 表示Promise被拒绝的原因的值。

二、Promise/A+规范关键规则解读与实现

2.1 Promise状态: Promise必须处于以下三种状态之一:待处理(pending)、已完成(fulfilled)或已拒绝(rejected)。

待处理: 可能转换为已完成或已拒绝状态。已完成: 不得转换到任何其他状态,且必须有一个值,该值不得更改。已拒绝: 不得转换到任何其他状态,且必须有一个原因,该原因不得更改。

实现:通过state属性跟踪Promise的状态,并使用value和reason属性存储相应的值和原因。状态转换仅在pending状态下进行。

class YourPromise {    constructor(executor) {        this.state = 'pending';        this.value = undefined;        this.reason = undefined;        this.onFulfilledCallbacks = [];        this.onRejectedCallbacks = [];        const resolve = (value) => {            if (this.state === 'pending') {                this.state = 'fulfilled';                this.value = value;                this.onFulfilledCallbacks.forEach(callback => queueMicrotask(() => callback(this.value)));            }        };        const reject = (reason) => {            if (this.state === 'pending') {                this.state = 'rejected';                this.reason = reason;                this.onRejectedCallbacks.forEach(callback => queueMicrotask(() => callback(this.reason)));            }        };        try {            executor(resolve, reject);        } catch (error) {            reject(error);        }    }    // ...then方法实现 (见下文) ...}

登录后复制

2.2 then方法: Promise必须提供then方法来访问其当前或最终的值或原因。then方法接受两个可选参数:onFulfilled和onRejected。

onFulfilled和onRejected都是可选参数:如果不是函数,则必须忽略。如果onFulfilled是函数:在Promise完成之后调用,并以Promise的值作为第一个参数。在Promise完成之前不得调用,且不得多次调用。如果onRejected是函数:在Promise被拒绝之后调用,并以Promise的原因作为第一个参数。在Promise被拒绝之前不得调用,且不得多次调用。onFulfilled和onRejected必须作为函数调用(即没有this值)。then方法必须返回一个Promise。then可以被多次调用,回调按照调用顺序执行。

实现:then方法需要处理三种状态:pending、fulfilled和rejected。对于pending状态,回调需要入队;对于fulfilled和rejected状态,回调需要立即异步执行。 我们使用queueMicrotask确保回调在下一个微任务队列中执行,满足异步执行的要求。

    then(onFulfilled, onRejected) {        return new YourPromise((resolve, reject) => {            if (this.state === 'fulfilled') {                queueMicrotask(() => {                    try {                        const result = onFulfilled ? onFulfilled(this.value) : this.value;                        resolve(result);                    } catch (error) {                        reject(error);                    }                });            } else if (this.state === 'rejected') {                queueMicrotask(() => {                    try {                        const result = onRejected ? onRejected(this.reason) : this.reason;                        reject(result);                    } catch (error) {                        reject(error);                    }                });            } else {                this.onFulfilledCallbacks.push(() => {                    try {                        const result = onFulfilled ? onFulfilled(this.value) : this.value;                        resolve(result);                    } catch (error) {                        reject(error);                    }                });                this.onRejectedCallbacks.push(() => {                    try {                        const result = onRejected ? onRejected(this.reason) : this.reason;                        reject(result);                    } catch (error) {                        reject(error);                    }                });            }        });    }

登录后复制

2.3 catch方法 (可选): 为了方便,可以添加一个catch方法,它等同于then(null, onRejected)。

    catch(onRejected) {        return this.then(null, onRejected);    }

登录后复制

三、测试

您可以使用以下代码测试您的YourPromise类:

const promise = new YourPromise((resolve, reject) => {    setTimeout(() => resolve('success!'), 1000);});promise    .then(value => {        console.log('fulfilled with:', value);        return 'next step';    })    .then(value => {        console.log('chained with:', value);    });const promise2 = new YourPromise(resolve => resolve('immediately resolved!'));console.log('before then()');promise2.then(value => console.log('inside then():', value));console.log('after then()');

登录后复制

四、总结

本文提供了一个简化版的Promise实现,帮助您理解Promise/A+规范的核心概念和实现细节。 完整的Promise实现更为复杂,需要处理更多边缘情况和规范细节,例如Promise的链式调用、then方法返回Promise的处理等。 但这个简化版本足以帮助您掌握Promise的本质。 希望本文能够帮助您更好地理解和运用JavaScript Promise。

以上就是在 JavaScript 中创建您自己的 Promise的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2644469.html

(0)
上一篇 2025年3月7日 07:15:54
下一篇 2025年3月7日 07:16:04

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 连续迁移

    本文介绍如何使用 sequelize 迁移来修改数据库表结构,特别是针对一个名为 metadata 的表进行列重命名和删除操作。 首先,我们有一个 Sequelize 模型定义: module.exports = (sequelize, s…

    2025年3月7日
    000
  • 测试开发

    astro 博客模板安装与 dev.to 集成指南 本文将指导您安装 Astro 博客模板,并使用 Astro 5 的内容层 API 将 Dev.to 文章集成到您的网站中。 第一步:安装 Astro 博客模板 使用 npm 命令安装最新版…

    2025年3月7日
    200
  • 静态数据的 Sequelize 播种器

    关于如何在续集中进行播种的非常简短的帖子。 播种器是您在数据库中创建静态数据的方式,您希望这些数据无需用户创建即可显示。 这样做的目标是向此模型定义的待办事项应用程序中的非常基本的任务类型表添加一些静态数据: module.exports …

    2025年3月7日
    200
  • 【A部分SOLID Typescript简介

    SOLID原则是一套面向对象编程的设计原则,旨在创建更健壮、易维护和可扩展的代码。本文将通过TypeScript示例,简要介绍SOLID原则中的前三个原则:单一职责原则(SRP)、开闭原则(OCP)和里氏替换原则(LSP)。 S &#821…

    2025年3月7日
    200
  • js爬虫怎样进行异常处理

    JavaScript爬虫开发中,异常处理至关重要。 网络请求和HTML解析过程容易出错,有效的异常处理能确保爬虫程序的稳定运行。 try…catch语句是JavaScript中处理异常的主要方法。 以下示例演示如何使用try&#…

    2025年3月7日
    200
  • js数据库如何进行数据恢复

    JavaScript本身并非数据库,但可用于操作数据库。本文演示如何结合Node.js和Sequelize库实现JavaScript数据库数据恢复。 前提条件:已安装Node.js 以下步骤将指导您使用Sequelize操作数据库,并进行数…

    2025年3月7日
    200
  • js数据库怎样进行数据加密

    JavaScript数据库数据加密解密方法详解 本文介绍在javascript中如何安全地加密和解密数据库数据,主要涵盖两种方法:使用原生subtlecrypto api和第三方库crypto-js。 选择哪种方法取决于项目需求和安全性考量…

    2025年3月7日
    200
  • js数据库怎样保证数据一致性

    JavaScript数据库数据一致性策略: 为了确保JavaScript应用中数据库数据的完整性和一致性,我们可以运用多种策略,主要包括事务处理、锁机制和乐观锁。 1. 事务处理 (Transactions): 事务是维护数据一致性的基石。…

    2025年3月7日
    200
  • Conditional Rendering: Best Practices and Pitfalls to Avoid

    条件渲染:高效灵活地控制UI显示 条件渲染是根据特定条件动态显示不同内容或UI元素的关键技术,在构建动态交互式应用中不可或缺。然而,不当的条件渲染实现可能导致代码难以维护、错误频发或效率低下。本文将介绍条件渲染的最佳实践和常见陷阱,助您编写…

    2025年3月7日
    200
  • 设计令人愉快的维护中页面 HTML 和 CSS

    网站维护期间,一个设计精良的“维护中”页面至关重要,它能有效地向用户传达网站暂时停运的信息,并确保透明度和用户参与度。本文将深入探讨如何使用HTML和CSS设计这样的页面,使其兼具视觉吸引力、响应速度和功能性。 为什么“维护中”页面如此重要…

    2025年3月7日
    200

发表回复

登录后才能评论