ts: 实现promise

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.mzph.cn/news/842763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

很耐看的Go快速开发后台系统框架

序言 秉承Go语言设计思路&#xff0c;我们集成框架简单易用、扩展性好、性能优异、兼顾安全稳定&#xff0c;适合企业及初学者用来开发项目、学习。我们框架和市面上其他家设计的不同&#xff0c;简单一步做到的我们不会两步&#xff0c;框架能自动处理&#xff0c;绝不手动处…

Android LAME原生音频

前言 我想大家都做过录音的功能吧&#xff0c;首先想到的是不是MediaRecorder&#xff1f;今天我们不用MediaRecorder&#xff0c;而是使用LAME库自己编译音频编码模块&#xff0c;很明显&#xff0c;这个需要用到NDK。凡是涉及到音视频编解码这块的&#xff0c;都需要用到And…

驱动开发:内核MDL读写进程内存

100编程书屋_孔夫子旧书网 MDL内存读写是最常用的一种读写模式,通常需要附加到指定进程空间内然后调用内存拷贝得到对端内存中的数据,在调用结束后再将其空间释放掉,通过这种方式实现内存读写操作,此种模式的读写操作也是最推荐使用的相比于CR3切换来说,此方式更稳定并不会…

Java Web 应用开发基础 - JSP内置对象

每个JSP 页面在第一次被访问时&#xff0c;Web 容器都会把请求交给 JSP 引擎&#xff08;即一个 Java 程序&#xff09;去处理。JSP 引擎先将 JSP 翻译成一个 _jspServlet (实质上也是一个 Servlet) &#xff0c;然后按照Servlet的调用方式进行调用。 JSP 第一次访问时会翻译成…

13、Go Gin集成Viper配置

在Go语言中&#xff0c;Gin是一个高性能的Web框架&#xff0c;而Viper是一个用于配置处理的库&#xff0c;它可以处理各种格式的配置文件&#xff0c;并且可以很容易地与Gin框架集成。 1. 安装所需的包 go get -u github.com/spf13/viper 2. 创建配置文件 创建一个配置文件…

Vue组件通讯中eventbus兄弟组件数据传递的例子

在Vue中&#xff0c;Event Bus&#xff08;也称为事件总线&#xff09;是一个常用于组件间通信的模式&#xff0c;特别是当组件之间没有直接的父子关系时。下面是一个使用Event Bus在兄弟组件之间传递数据的简单例子。 首先&#xff0c;你需要创建一个Event Bus实例。这通常是…

ios:Command PhaseScriptExecution failed with a nonzero exit code

问题 使用 xcode 跑项目真机调试的时候&#xff0c;一直报错 Command PhaseScriptExecution failed with a nonzero exit code。 解决 最终靠以下方法解决 删除Podfile.lock文件删除Pods文件删除.xcworkspace文件Pod installCommandShiftK 清理一下缓存 亲测有效

滑动窗口-java

主要通过单调队列来解决滑动窗口问题&#xff0c;得到滑动窗口中元素的最大值和最小值。 目录 前言 一、滑动窗口 二、算法思路 1.滑动窗口 2.算法思路 3.代码详解 三、代码如下 1.代码如下 2.读入数据 3.代码运行结果 总结 前言 主要通过单调队列来解决滑动窗口问题&#xff…

vue组件通讯props和$emit的例子

当然&#xff0c;我可以为你提供一个使用 Vue 组件通讯的示例&#xff0c;特别是通过 props 和 $emit 的方式。 子组件 (ChildComponent.vue) vue <template> <div> <button click"notifyParent">点击我通知父组件</button> <p>父组…

Gitee的原理及应用详解(五)

本系列文章简介&#xff1a; Gitee是一款开源的代码托管平台&#xff0c;是国内最大的代码托管平台之一。它基于Git版本控制系统&#xff0c;提供了代码托管、项目管理、协作开发、代码审查等功能&#xff0c;方便团队协作和项目管理。Gitee的出现&#xff0c;在国内的开发者社…

Leetcode刷题笔记5

76. 最小覆盖子串 76. 最小覆盖子串 - 力扣&#xff08;LeetCode&#xff09; 解法一&#xff1a; 暴力枚举 哈希表 先定义left和right&#xff0c;可以在随机位置 枚举一个位置向后找&#xff0c;找到一个位置之后&#xff0c;发现这段区间是一个最小的区间之后&#xff0c…

vue3+ts 中使用mitt进行跨组件通信

mitt插件的使用 安装插件进行封装一个模块&#xff0c;对外暴露一个Mitt实例使用 安装插件 官方文档 pnpm i mitt --s //我用的pnpm 或 npm i --s mitt 或 yarn add mitt进行封装一个模块&#xff0c;对外暴露一个Mitt实例 1、在utils文件夹下新建mitt&#xff08;例如 mitt…

【探索数据之美】“从基础到精通——深入解析数据结构与二叉树的秘密“

gitee代码获取链接&#xff1a;https://gitee.com/flying-wolf-loves-learning/data-structure.git 一、树的概念 1.1 概念简述 数据结构中的树是一种层次结构&#xff0c;它由节点&#xff08;node&#xff09;和边&#xff08;edge&#xff09;组成。每个节点都有零个或多…

解决鼠标滚动时element-ui下拉框错位的问题

问题描述&#xff1a;elementUi的el-select下拉选择框,打开之后,直到失去焦点才会自动关闭。 在有滚动条的弹窗中使用时就会出现打开下拉框,滚动弹窗,el-select下拉框会超出弹窗范围的问题. 解决方案&#xff1a; 1、先在util文件夹下创建个hideSelect.js文件&#xff0c;代码…

数据结构(六)队列

文章目录 一、概念二、逻辑结构&#xff1a;线性结构三、存储结构&#xff08;一&#xff09;顺序队列&#xff08;二&#xff09;循环队列1. 结构体定义2. 创建队列&#xff08;1&#xff09;函数定义&#xff08;2&#xff09;注意点&#xff08;3&#xff09;代码实现 3. 入…

2024系分真题 网上回忆版

一、综合知识题目 计算机系统基础&#xff1a;进制表示范围;缺页次数计算;RAID. 网络与安全:TCP/IP协议(ftp):&#xff1a;协议(SSL和IPSec);数字签名;加密算法。 通信&#xff1a;三网合一&#xff0c;香农定理&#xff0c;FTP、SSL什么协议 数据库设计&#xff1a;1&…

改进rust代码的35种具体方法-类型(十九)-避免使用反射

上一篇文章 从其他语言来到Rust的程序员通常习惯于将反思作为工具箱中的工具。他们可能会浪费很多时间试图在Rust中实现基于反射的设计&#xff0c;却发现他们所尝试的事情只能做得不好&#xff0c;如果有的话。这个项目希望通过描述Rust在反思方面做什么和不做什么&#xff0c…

C语言例题47、从键盘输入一个正整数n,计算1+1/(1+2)+1/(1+2+3)+…+1/(1+2+3+…+n) 的值

#include <stdio.h>void main() {int x;int fm 0;//分母double sum 0;printf("请输入一个正整数&#xff1a;");scanf("%d", &x);for (int i 1; i < x; i) {fm i;//分母变化sum sum 1.0 / fm;if (i ! x) {printf("1/%d ", f…

【Linux】升级GCC(版本9.3),补充:binutils

GCC&#xff1a;GNU Compiler Collection 。编译器&#xff0c;几乎Linux中所有程序&#xff08;包括内核&#xff09;都是gcc编译的&#xff0c;包括libc。 gcc不仅仅是编译器&#xff0c;gcc也有很多库&#xff0c;依赖libc。gcc和libc互相依赖。 GCC官网&#xff1a;GCC, …

【CMake】CMake入门(二)流程控制 if while foreach 数学表达式 函数定义

本篇文章不是新手入门教学文章&#xff0c;主要是记录笔者个人的学习笔记 参考文章 : CMake中的分支与判断&#xff08;if语句&#xff09;CMake中的条件判断if/elseif/else CMake入门&#xff08;二&#xff09; 一、CMake中的逻辑判断二、 while循环三、CMake中的foreach循环…