当前位置: 首页 > news >正文

手写Promise

构造器的实现

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;}
}
const p = new MyPromise((resolve, reject) =>{resolve(1);
});
  • Promise 的状态一旦定下来之后,在后续的所有过程中都不可能再去改变它的状态了
  • 如果再执行过程中报错,会执行rejected,但是捕获不到异步错误

Promise-then的回调执行时机

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;#handlers = [];constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;this.#run();}#run(){if(this.#state === PENDING) return;while(this.#handlers.length){const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift();if(this.#state === FULFILLED){if(typeof onFulfilled === 'function'){onFulfilled(this.#result)}}else{if(typeof onRejected === 'function'){onRejected(this.#result)}}}}then(onFulfilled, onRejected){return new MyPromise((resolve, reject) =>{this.#handlers.push({onFulfilled,onRejected,resolve,reject,});this.#run();});}
}const p = new MyPromise((resolve, reject) =>{setTimeout(()=>{resolve(123);},1000)
});p.then((res) =>{console.log('promise 成功1', res);}, (err) =>{console.log('promise 失败1', err);}
);
p.then((res) =>{console.log('promise 成功2', res);}, (err) =>{console.log('promise 失败2', err);}
);
p.then((res) =>{console.log('promise 成功3', res);}, (err) =>{console.log('promise 失败3', err);}
);

为了判断什么时候调用,所以用一个handlers数组记录,并用run函数调用

Promise-then 的返回值

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;#handlers = [];constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;this.#run();}// 判断一个函数是不是Promise(是否满足A+规范)#isPromiseLike(value){return value && typeof value.then === 'function' && (typeof value === 'object' || typeof value === 'function');}// 把一个函数放到微队列#runMicroTask(func){// node nextTickif(process && process.nextTick){process.nextTick(func);}// 浏览器 MutationObserverelse if(typeof MutationObserver === 'function'){const ob = new MutationObserver(fn);const text = document.createTextNode('1');ob.observe(text, { characterData: true});text.data = '2';}else{setTimeout(fn, 0);}}#runOne(callback, resolve, reject){this.#runMicroTask(()=>{if(typeof callback !== 'function'){const settled = this.#state === FULFILLED ? resolve : reject;settled(this.#result);return;}try {const data = callback(this.#result);if(this.#isPromiseLike(data)){data.then(resolve, reject);}else{resolve(data);}} catch (err) {reject(err);}});}#run(){if(this.#state === PENDING) return;while(this.#handlers.length){const {onFulfilled, onRejected, resolve, reject} = this.#handlers.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.#handlers.push({onFulfilled,onRejected,resolve,reject,});this.#run();});}
}const p = new MyPromise((resolve, reject) =>{setTimeout(()=>{reject(123);},1000)
});p.then(null, (err) =>{console.log('promise 失败', err);return 456;}
).then((data) =>{console.log("ok",data);
});

这里有三种情况:

  • 对应的回调不是函数的情况
  • 回调是一个函数的情况
  • 返回结果是一个Promise的情况

相关文章:

手写Promise

构造器的实现 const PENDING pending; const FULFILLED fulfilled; const REJECTED rejectedclass MyPromise{#state PENDING;#result undefined;constructor(executor){const resolve (data) > {this.#changeState(FULFILLED, data);};const reject (reason) > …...

深度学习云服务器免费使用教程

#云服务器# #深度学习# #人工智能# #计算机视觉# 本文为各位学习深度学习的入门选手而创建,降低深度学习的入门门槛。 谷歌云服务器Colab: T4GPU。限额,需要科学上网,不能使用终端。 谷歌云服务器地址:欢迎使用 C…...

使用ansible的剧本制作salt-master与salt-minion的安装与启动服务过程

虚拟机版本:Rocky Linux release 8.6 (Green Obsidian) 准备几台虚拟机 ipv4地址主机名192.168.137.13center192.168.137.14sp-1192.168.137.15sp-2192.168.137.16sp-3 一、center主机的配置 1.vim /etc/hosts 127.0.0.1 localhost localhost.localdomain loc…...

数据库sqlite3

用数据库函数完成数据的增删改查 增: 将要存储的信息录入到结构体中,再使用snprintf函数信息结合sqlite3命令语句使用sqlite3_exec函数完成插入。 int do_insert(sqlite3 *ppDb) {Worker Work;printf("输入插入的工号:");scanf("%d&qu…...

开发基础之Python 函数(Basic Python Functions for Development)

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…...

Django_Vue3_ElementUI_Release_001_项目初始化

1. 数据库 1.1 安装 https://blog.csdn.net/rbx508780/article/details/127176754 1.2 创建数据库 1.3 DBeaver可视化数据库 https://dbeaver.io/download/ 2 安装Python(3.9.12) 2.1 下载地址 https://www.python.org/downloads/release/python-3912/ 2.2 设定国内源 pip …...

MySQL之安装与基础知识

目录 一:在centos7上安装MySQL数据库 1.卸载默认存在的环境 2.配置mysql的yum源 3. 安装MySQL 4.登录mysql 5.设置MySQL的配置文件 二:MySQL基础知识 1.什么是数据库 2.主流数据库 3.服务器,数据库,表关系及使用案例 4…...

前端基础 | HTML基础:HTML结构,HTML常见标签

文章目录 HTML1、HTML结构1.1HTML标签1.1.1标签1.1.2标签含义 1.2HTML文件基本结构1.3标签层次结构1.4 快速生成代码框架 2、HTML常见标签2.1注释标签2.2标题标签:h1–h62.3段落标签:p2.4 换行标签:br2.5格式化标签2.6 图片标签:i…...

宏任务和微任务+超全面试真题

概念 微任务和宏任务是在异步编程中经常使用的概念,用于管理任务的执行顺序和优先级。 宏任务:setTimeout, setInterval,I/O 操作和 UI 渲染等。微任务: Promise 回调、async/await等 微任务通常比宏任务具有更高的优先级。 执…...

针对SVM算法初步研究

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝心态决定高度,细节决定成败…...

Java中的`String`不可变性详解

在Java中,String类具有不可变性(immutable),这意味着一旦String对象被创建,它的值将无法更改。所有对字符串的修改操作(如拼接、替换等)实际上都会生成一个新的字符串对象,而不会修改…...

c# SMTP发送邮件

string from ""; string fromAlias "MIS-TC"; string[] to { "" }; string subject "问题提交"; string body sb.ToString(); string ipaddr "smtp.email.qq.com"; int port 25; string credit ""; strin…...

GPU基础 -- 并行化与阿姆达尔定律

并行化与阿姆达尔定律 并行化是将计算任务分割成多个部分,使这些部分能够在多个处理器或核心上同时运行,从而加速任务的完成时间。阿姆达尔定律(Amdahl’s Law)则揭示了并行化所能带来的加速效果的限制。 阿姆达尔定律公式 阿姆…...

Lua热更

Lua 热更 前提 Lua是轻量级,可以解释执行的编程语言、性能好 基本原则 1.场景空 代码控制物体加载释放 2.场景一个 3.节点不手动挂代码 4.AssetsBundle资源管理 5.Lua开发框架 6.调试模式、发布模式 XLua 热更框架 XLua是C#环境下Lua的解决方案 1.Lua虚拟…...

提升汽车行业软件质量:ASPICE培训的关键实践方法

ASPICE(汽车行业软件过程改进和能力确定)培训是一种针对汽车行业软件开发和维护过程的标准化培训。 该培训旨在帮助组织提高其软件开发和维护过程的质量和效率。以下是ASPICE培训的一些最佳实践方法: 1. 理解ASPICE框架:首先&…...

2024 全新智能识别 API 接口震撼登场

近年来,随着人工智能技术的快速发展,智能识别技术逐渐成为了各个领域的热门应用。在这个大背景下,2024 年的全新智能识别 API 接口横空出世,为我们的生活带来了更多的便利。本文将为大家详细介绍这个全新智能识别 API 接口&#x…...

《UniVS: Unified and Universal Video Segmentation with Prompts as Queries》要点提炼

论文来源:https://arxiv.org/abs/2402.18115 《UniVS: Unified and Universal Video Segmentation with Prompts as Queries》是2024CVPR中的一篇关于视频分割的论文, 主要内容: 论文提出了一个名为UniVS的新型统一视频分割架构&#xff0c…...

计算机毕业设计选题推荐-推拿知识互动平台-Java/Python项目实战

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

基于SpringBoot+Vue+MySQL的瑜伽馆管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 本系统采用SpringBoot作为后端框架,Vue.js构建前端用户界面,MySQL作为数据库存储系统,实现了瑜伽馆的全面数字化管理。系统涵盖会员管理、课程预约、教练排班、收入统计等功能模块&#xff0c…...

【MySQL】EXPLAIN(执行计划)关键字是什么?

简介: explain是一个强大的 SQL 命令,用于分析和优化查询性能。通过查看数据库执行计划,我们可以理解查询是如何被处理的,包括表的访问顺序、使用的索引、连接类型等。这对于找到潜在的性能瓶颈非常重要。 目录 一、基本含义 二…...

Mybatis两种方式来调用sql语句

使用Mybatis时,有两种方式来调用sql语句: 方式一(直接通过Session对象调用sql语句): SqlSession sqlSession sqlSessionFactory.openSession(); User user sqlSession.selectOne("userTest.selectUser"…...

第十八节:学习统一异常处理(自学Spring boot 3.x的第五天)

这节记录下如何通过AOP方式统一处理异常拦截。 第一步: 新建一个exception包,创建一个ExcetionHandler.java(名字随意取) package cn.wcyf.wcai.exception;import cn.wcyf.wcai.common.Result; import org.springframework.web…...

flink中slotSharingGroup() 的详解

在 Apache Flink 中,slotSharingGroup() 是一个用于控制算子(operator)之间资源共享的机制。它允许多个算子共享相同的 slot(即资源容器)。Slot 是 Flink 中的资源单位,slot 共享可以提高资源利用率&#x…...

ASPF 技术介绍

...

77-java 装饰器模式和适配器模式区别

‌Java中的装饰器模式和适配器模式虽然都涉及到对象的组合和包装,但它们的应用场景和目的有所不同。‌ ‌装饰器模式的目的是在不修改原始对象的基础上,动态地添加功能或行为。‌它允许用户通过创建一个包含原始对象的包装类(装饰器&#xff…...

5. Fabric 设置画布大小

1. 设置宽度 canvas.setWidth(width)2. 设置高度 canvas.setHeight(height)3. 设置大小 canvas.setDimensions({width,height })4. 画布的缩放 canvas.on(mouse:wheel, (opt) > {const delta opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下…...

240912-通过Ollama实现网站知识总结

A. 最终效果 B. 准备工作 报错: USER_AGENT environment variable not set, consider setting it to identify your requests.-CSDN博客 C. 完整代码 # https://coreyclip.github.io/Ollama-Web-Summaries/import os os.environ[USER_AGENT] Mozilla/5.0 (Windows NT 10.…...

Debian 包管理工具apt使用

apt基本用法 apt(Advanced Package Tool)是Debian及其衍生发行版(如Ubuntu、Linux Mint等)中非常强大的软件包管理系统。它允许用户从远程仓库安装、更新、升级、配置和卸载软件包。除了我们已经讨论过的卸载软件包的功能外&…...

如何模拟一个小程序项目打包的流程

一、Uni-app 执行 yarn run dev:mp-weixin后会发生什么 (一)准备工作 克隆项目:创建以 typescript 开发的工程(如命令行创建失败,请直接访问 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts.z…...

设计模式七大原则详解

设计模式七大原则详解 设计模式中的“七大原则”是面向对象编程(OOP)中的一组指导原则,这些原则帮助开发者编写灵活、可维护、可扩展的代码。这些原则并不直接等同于设计模式,但它们是设计模式的基础。下面是这七大原则&#xff…...