ts: 实现promise

ops/2024/9/20 1:15:25/ 标签: typescript

ts实现的promise和js实现的promise有什么使用上的区别

  1. 类型注解
    可以为 Promise 指定明确的返回类型,如 Promise< string>、Promise<number[]> 等。这有助于在编译时捕获类型错误
  2. 类型推断
    ts的类型推断功能可以自动推断出 Promise 的返回类型, 提高了代码的可读性。
  3. 类型安全性
    如果你尝试将一个 Promise 的解析值赋给一个不兼容的类型,TypeScript 编译器会报错。
  4. 更好的文档和代码提示
    再ide中会提供更好的文档和代码提示,包括 Promise 的类型信息、参数列表、返回值等,有助于你更快地理解代码并减少错误

示例1

// 示例: myPromise.resolve类型推断
let aa1 = myPromise.resolve("123");
let aa2 = Promise.resolve("123");

示例2

// 示例: Promise<string> 是一个类型注解
// 定义一个返回Promise<string>的函数
// let myPromise: Promise<string>;
// myPromise = new Promise((resolve, reject) => {
//   // ... 异步操作
//   resolve('这是另一个返回的字符串数据');
// });
function fetchMessageFromServer(): myPromise<string> {// 假设这是一个模拟的异步操作,例如从服务器获取数据return new myPromise<string>((resolve, reject) => {setTimeout(() => {// 模拟成功获取数据const message = 123;resolve(message); // 解析并返回字符串}, 2000); // 假设这个操作需要2秒钟});
}// 使用fetchMessageFromServer函数并处理其结果
fetchMessageFromServer().then((message) => {console.log(message); // 输出:Hello from the server!console.log(message.length); // 输出:21}).catch((error) => {console.error("An error occurred:", error);});// 注意:在TypeScript中,通常不需要显式指定.then和.catch的参数类型,因为它们可以从Promise的泛型参数中推断出来。// 如果你使用async/await语法,代码会更加简洁和直观:
async function printMessageFromServer() {try {const message = await fetchMessageFromServer();console.log(message); // 输出:Hello from the server!console.log(message.length); // 输出:21} catch (error) {console.error("An error occurred:", error);}
}printMessageFromServer();

ts实现promise代码

// 2.1 promise有三个状态
const PENDING = "pending"; // 等待
const FULLFILLED = "fullfilled"; // 成功
const REJECTED = "rejected"; // 失败// 1. promise是一个类, 执行类需要传递构造函数并立即执行
class myPromise<T> {constructor(executor) {// 构造函数constructor是一个类必须要有的方法,默认返回实例对象try {executor(this.resolve, this.reject);} catch (e) {this.reject(e);}}status = PENDING; // 状态value: T; // 成功的值默认是没有的是undefinedreason: any; // 失败的值默认是没有的是undefinedsuccessCallback: Array<((value: T) => any) | null> = [];fallCallback: Array<((reason: any) => any) | null> = [];resolve = (value: T) => {// 2.2 如果状态不是等待,阻止程序向下执行(因为Promise有三个状态,只能 pending -> fullfilled / pending -> rejected, 一旦状态确定就不可改变)if (this.status !== PENDING) return;this.status = FULLFILLED; // 更改状态为成功this.value = value; // 保存成功的值// 5.2 判断成功回调函数是否存在,存在调用// this.successCallback && this.successCallback(this.value)// while (this.successCallback.length) this.successCallback.shift()(this.value)while (this.successCallback.length) {const callback = this.successCallback.shift();if (callback) callback(this.value);}// this.successCallback.shift()();}; // 箭头函数让函数内部指向类reject = (reason) => {// 2.3 如果状态不是等待,阻止程序向下执行(因为Promise有三个状态,只能 pending -> fullfilled / pending -> rejected, 一旦状态确定就不可改变)if (this.status !== PENDING) return;this.status = REJECTED; // 更改状态为失败this.reason = reason; // 保存失败的原因// 5.2 判断失败回调函数是否存在,存在调用// this.fallCallback && this.fallCallback(this.reason)// while (this.fallCallback.length) this.fallCallback.shift()(this.reason)// while (this.fallCallback.length) this.fallCallback.shift()();while (this.fallCallback.length) {const callback = this.fallCallback.shift();if (callback) callback(this.reason);}};then(successCallback?: (value: T) => any,fallCallback?: (reason: any) => any) {// ???这两行代码意义何在successCallback = successCallback ? successCallback : (value) => value;fallCallback = fallCallback? fallCallback: (reason) => {throw reason;};// 11. 传递console.log("this.status", this.status);// 返回promise对象可进行链式调用,并在把上一个then传给下一个thenlet promise2 = new myPromise((resolve, reject) => {// 3. then方法内部就是判断状态的,状态是成功调用成功回调,失败调用失败回调if (this.status === FULLFILLED) {// 9.2 同步代码执行后就可以拿到promise// setTimeout(() => {try {// 4.1 then成功的回调有一个参数,表示成功的值(默认是空的,就是undefined)let x = successCallback(this.value);// 判断x的值是普通值还是promise对象// 如果是普通值直接resolve// 如果是promise对象则查看返回的结果,根据这个结果决定调用resolve还是reject// resolve(x)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}// }, 0)} else if (this.status === REJECTED) {// 4.2 then失败的回调有一个参数,表示失败的原因// fallCallback(this.reason)// let y = fallCallback(this.reason)// reject(y)// setTimeout(() => {try {// 4.1 then成功的回调有一个参数,表示成功的值(默认是空的,就是undefined)let x = fallCallback(this.reason);// 判断x的值是普通值还是promise对象// 如果是普通值直接resolve// 如果是promise对象则查看返回的结果,根据这个结果决定调用resolve还是reject// resolve(x)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}// }, 0)} else {// 等待状态// 5.1  将成功和失败的状态存储起来// this.successCallback = successCallback// this.fallCallback = fallCallback// this.successCallback.push(successCallback)// this.fallCallback.push(fallCallback)this.successCallback.push(() => {// setTimeout(() => {try {// 4.1 then成功的回调有一个参数,表示成功的值(默认是空的,就是undefined)let x = successCallback(this.value);// 判断x的值是普通值还是promise对象// 如果是普通值直接resolve// 如果是promise对象则查看返回的结果,根据这个结果决定调用resolve还是reject// resolve(x)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}// }, 0)});this.fallCallback.push(() => {// setTimeout(() => {try {// 4.1 then成功的回调有一个参数,表示成功的值(默认是空的,就是undefined)let x = fallCallback(this.reason);// 判断x的值是普通值还是promise对象// 如果是普通值直接resolve// 如果是promise对象则查看返回的结果,根据这个结果决定调用resolve还是reject// resolve(x)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}// }, 0)});}});return promise2;}finally(callback) {return this.then((value) => {// callback()// return valuereturn myPromise.resolve(callback()).then(() => value);},(reason) => {// callback()// // throw reason ???为什么我这么不会执行到finally后面的then// return reasonreturn myPromise.resolve(callback()).then(() => {throw reason;});});}catch(fallCallback) {return this.then(undefined, fallCallback);}static all(array) {// 如果是promise保存结果,如果是普通值也保存下来,最后一并返回let result: any[] = [];let index = 0;console.log("all");return new myPromise((resolve, reject) => {function addData(key: number, value) {result[key] = value;index++;if (index === array.length) {resolve(result);}}for (let i: number = 0; i < array.length; i++) {let current = array[i];if (current instanceof myPromise) {// promise 对象current.then((value) => addData(i, value),(reason) => reject(reason));} else {// 普通值addData(i, array[i]);}}});}static resolve(value) {if (value instanceof myPromise) return value;return new myPromise((resolve) => resolve(value));}
}function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {// 9.1 避免then中同一个promise循环返回return reject(new TypeError("Chaining cycle detected for promise #<Promise>"));}if (x instanceof myPromise) {// x.then((value) => {resolve(value)}, reason => reject(reason))x.then(resolve, reject);} else {resolve(x);}
}// 在node中
// module.exports = myPromise
// 在es6中
// export const myPromise = myPromise

http://www.ppmy.cn/ops/44474.html

相关文章

Python代码:十七、生成列表

1、题目 描述&#xff1a; 一串连续的数据用什么记录最合适&#xff0c;牛牛认为在Python中非列表&#xff08;list&#xff09;莫属了。现输入牛牛朋友们的名字&#xff0c;请使用list函数与split函数将它们封装成列表&#xff0c;再整个输出列表。 输入描述&#xff1a; …

【学习心得】超简单的加载模型和保存模型的方法

方法一&#xff1a;pickle库 这是Python的标准序列化模块&#xff0c;可以将几乎任何Python对象转化为字节流&#xff08;即序列化&#xff09;&#xff0c;然后可以将其存储到文件中或通过网络发送。之后&#xff0c;可以使用pickle再次加载这个字节流&#xff0c;恢复原始对象…

【C++面试100问】第八十五问:有了const,C++11为什么还要引入constexpr

B站讲解视频 在大部分实际场景中&#xff0c;const 和 constexpr 是可以混用的&#xff1b;但是在创建数组用修饰的变量指定size的时候&#xff0c;只能用constexpr&#xff1b;总的来说&#xff0c;在 C 11 标准中&#xff0c;const 用于为修饰的变量添加“只读”属性&#xf…

Vue从入门到实战Day07

一、vuex概述 目标&#xff1a;明确vuex是什么&#xff0c;应用场景&#xff0c;优势 1. 是什么&#xff1a; vuex是一个vue的状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;vuex是一个插件&#xff0c;可以帮助我们管理vue通用的数据&#xff08;多组件共享的…

接口响应断言-json

json认识JSONPath源码类学习/json串的解析拓展学习 目的&#xff1a;数据返回值校验测试 json认识 json是什么-是一种数据交换格式&#xff0c;举例平时看到的json图2&#xff0c;在使用中查看不方便&#xff0c;会有格式转化的平台&#xff0c;json格式的展示 JSON在线视图…

datasheet芯片数据手册—新手入门学习(二)【8-18】

参考芯片手册已经上传&#xff0c;可自行下载 因为芯片参考手册内容比较多&#xff0c;故再一次介绍本文内容主要讲解章节。 目录 8、内容介绍 命令真值表 9、Command Definitions 10、READ Operations &#xff08;1&#xff09;页面读取操作 &#xff08;2&#xff…

Kubernetes Service 之原理与 ClusterIP 和 NodePort 用法

Kubernetes Service 之原理与 ClusterIP 和 NodePort 用法 Service 定义 在 Kubernetes 中&#xff0c;由于Pod 是有生命周期的&#xff0c;如果 Pod 重启它的 IP 可能会发生变化以及升级的时候会重建 Pod&#xff0c;我们需要 Service 服务去动态的关联这些 Pod 的 IP 和端口…

openssh生成ed25519的密钥对并实现服务器间免密钥登录

本文讲解如何用openssh生成ed25519的密钥对并实现服务器间免密钥登录。 注意&#xff1a;所有操作均在客户机侧 一、生成 ED25519 密钥 用需要免密登录的用户&#xff08;本例为username&#xff09; 运行“ssh-keygen -t ed25519 -b 256” [usernamelocalhost ~]$ ssh-keyge…

js怎么生成验证码?js生成指定长度的随机字符串

在项目中经常有生成随机字符串的需求&#xff0c;比如验证接口签名、验证码(Node.js发送短信或邮箱验证码、生成图片验证码)&#xff0c;我们可以使用Javascript生成随机字符。 使用随机数从给出的可能字符中抽取合并字符串 优点是可以自定义结果中字符的取值&#xff0c;比如…

探索旅行的优惠之选,千益畅行旅游卡让旅程更省心省力!

在旅行的道路上&#xff0c;一张旅游卡往往能为您带来意想不到的便利与优惠。那么&#xff0c;对于千益畅行旅游卡&#xff0c;您是否好奇如何轻松拥有它呢&#xff1f; 首先&#xff0c;千益畅行旅游卡作为旅行者的贴心伴侣&#xff0c;为您提供了多样化的获取渠道。您可以通…

Flutter 中的 SelectableText 小部件:全面指南

Flutter 中的 SelectableText 小部件&#xff1a;全面指南 在 Flutter 应用开发中&#xff0c;展示文本是常见需求之一&#xff0c;SelectableText 是 Flutter 提供的一个用于显示可选文本的小部件。它允许用户选择文本的一部分或全部&#xff0c;进行复制等操作&#xff0c;这…

WordPress安装插件失败No working transports found

1. 背景&#xff08;Situation&#xff09; WordPress 社区有非常多的主题和插件&#xff0c;大部分人用 WordPress 都是为了这些免费好用的主题和插件。但是今天安装完 WordPress 后安装插件时出现了错误提示&#xff1a;“ 安装失败&#xff1a;下载失败。 No working trans…

设计模式10——装饰模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 装饰模式 是一种结构型模式。…

Java 文件操作和输入输出流

在 Java 编程中&#xff0c;文件操作和输入输出流是非常常见和重要的任务&#xff0c;它们允许你读取和写入文件、处理数据流等。 文件操作概述 文件操作是指对文件进行创建、读取、写入、删除等操作的过程。在 Java 中&#xff0c;文件操作通常涉及到使用文件对象、输入输出…

基于香橙派搭建家庭网盘

一、概述 家庭网盘是一种用于家庭用户的在线存储和文件共享服务。它允许家庭成员在云端存储、同步和分享照片、视频、文档等文件&#xff0c;方便快捷地访问和管理个人和家庭数据。家庭网盘通常提供安全可靠的数据存储和备份功能&#xff0c;保障用户数据的安全性。此外&#x…

java项目级云MES源码(制造执行系统) springboot + vue-element-plus-admin生产制造业MES系统源码

java项目级云MES源码&#xff08;制造执行系统) springboot vue-element-plus-admin生产制造业MES系统源码 MES系统通过信息传递对从订单下达到产品完成的整个生产过程进行优化管理。当工厂发生实时事件时&#xff0c;MES制造执行系统功能的发挥重点体现在及时做出反应、报告&…

高效编写大模型 Prompt 提示词,解锁 AI 无限创意潜能

随着 ChatGPT 的出现&#xff0c;AI 成为新的焦点&#xff0c;有人说过“未来 50%的工作将是提示词工作”&#xff0c;目前很多公司也在开始招聘 Prompt 提示词工程师。Prompt&#xff08;提示词&#xff09;成为了连接创意与技术的桥梁&#xff0c;它不仅是简单的指令&#xf…

Rom应用开发遇到得一些小bug

记录一些细碎得bug ROM时间类问题 问题描述&#xff1a; 设备拔电重启&#xff0c;ROM时间为默认时间如1970年1月1日&#xff0c;与某些业务场景互斥 问题原因&#xff1a; 后台接口校验https证书校验失败&#xff0c;要求是2年内得请求头校验了时间戳&#xff0c;时间戳过期…

leetcode-560 和为k的数组

一、题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 注意&#xff1a;nums中的元素可为负数 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2输入&#xff1a;num…

MyBatisPlus实现多表查询

前言 在现代Web开发中,数据操作层的高效与灵活至关重要。MyBatisPlus(简称MP)作为MyBatis的增强工具,凭借其简洁的API设计和丰富的功能,极大地简化了数据库操作,尤其是在处理复杂查询如多表关联查询时展现出了独特的优势。本文将通过一个实际案例——使用MyBatisPlus实现…