JS异步进化与Promise

JavaScript 是单线程的,但它并不是无法处理异步操作。相反,JavaScript 的单线程特性和其事件循环机制使得它在处理异步任务方面非常高效

回调函数(Callback Functions)

一开始JS使用回调的形式来处理异步的结果,但是异步的弊端很大

例如:无法更好的处理错误,无法追溯数据来源,无法使用同步,回调地狱等问题

console.log("开始");setTimeout(() => {console.log("异步操作完成");
}, 1000);console.log("结束");//result开始
结束
异步操作完成

回调地狱是最头疼的,所以就需要改变他

setTimeout(() => {console.log("第一步完成");setTimeout(() => {console.log("第二步完成");setTimeout(() => {console.log("第三步完成");}, 1000);}, 1000);
}, 1000);

Promise(Promise A+ 规范)

所谓Promise 就是一个承诺

Promise的状态

  • Pending(待定): 初始状态,既不是成功也不是失败
  • resolved / fullfilled (已完成): 表示操作成功完成
  • Rejected(已失败): 表示操作失败
//初始状态
let promise = new Promise((resolve, reject) => {// promise 初始状态是 pending
});//Fulfilled
let promise = new Promise((resolve, reject) => {resolve('成功的结果');
});promise.then((value) => {console.log(value); // 输出: 成功的结果
});//Rejected
let promise = new Promise((resolve, reject) => {reject('失败的原因');
});promise.catch((reason) => {console.log(reason); // 输出: 失败的原因
});

切记你从一个状态改变到另一个状态后就无法再改变了

Promise的存储

Promise 的状态可以从 pending 变为 fulfilledrejected,但一旦变为 fulfilledrejected,就不能再变为其他状态。这种状态的不可变性确保了 Promise 的一致性和可靠性,每一种状态都会有定义的返回的值

当执行函数调用 resolve 时,Promise 的状态从 pending 变为 fulfilled

resolve 可以接受一个参数,作为 Promise 成功的值, PromiseResult变为存储的数据 , 调用then的第一个回调函数来返回数据

let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve('成功的结果');}, 1000);
});promise.then((value) => {console.log(value); // 1秒后输出: 成功的结果
});

当执行函数调用 reject 时,Promise 的状态从 pending 变为 rejected

reject 可以接受一个参数,作为 Promise 失败的原因, PromiseResult变为存储的数据 或 异常对象

let promise = new Promise((resolve, reject) => {setTimeout(() => {reject('失败的原因');}, 1000);
});promise.catch((reason) => {console.log(reason); // 1秒后输出: 失败的原因
});

Promise实例方法

.then

  • 用于指定当 Promise 成功时的回调函数
  • 它接受两个参数,第一个是成功时的回调函数onFulfilled
  • 第二个是失败时的回调函数onRejected(可选)
  • 返回一个新的 Promise 对象
const p1 = new Promise((resolve, reject) => {resolve("成功!");// 或// reject(new Error("错误!"));
});p1.then((value) => {console.log(value); // 成功!},(reason) => {console.error(reason); // 错误! //但是这个回调不常用,建议使用.catch},
);

.catch

  • 用于指定当 Promise 失败时的回调函数onRejected
  • 抛出错误也可以使状态变为Rejected
  • Promise已对现,则catch不会被调用
  • 返回一个新的 Promise 对象
let promise = new Promise((resolve, reject) => {reject('失败');
});promise.catch(function(reason) {console.log(reason); // 失败
});

.finally

  • 用于指定不论 Promise 最终状态如何都会执行的回调函数
  • 返回一个新的 Promise 对象
function checkMail() {return new Promise((resolve, reject) => {if (Math.random() > 0.5) {resolve('Mail has arrived');} else {reject(new Error('Failed to arrive'));}});
}checkMail().then((mail) => {console.log(mail);}).catch((err) => {console.error(err);}).finally(() => {console.log('Experiment completed');});

 Promise静态方法

.resolve

  • 返回一个成功的以给定值解析后的 Promise 对象
  • 如果传入的参数是一个 Promise 对象,则参数的结果直接影响返回值
  • 如果不是Promise 对象,那么就直接返会成功的Promise 对象
  • 该函数将嵌套的类 Promise 对象(例如,一个将被兑现为另一个 Promise 对象的 Promise 对象)展平,转化为单个 Promise 对象,其兑现值为一个非 thenable
Promise.resolve(42).then(function(value) {console.log(value); // 42 //resolve
});let p1 = Promise.resolve(521);
console.log(p1)  //resolve

.reject

  • 返回一个失败的 Promise
  • 无论参数的形式,结果都是失败的,哪怕是成功的Promise
function resolved(result) {console.log('Resolved');
}function rejected(result) {console.error(result);
}Promise.reject(new Error('fail')).then(resolved, rejected);
// Expected output: Error: fail

.all

  • 接受一个包含多个 Promise 的数组,返回的也是数组
  • 返回一个新的 Promise, 当所有传入的 Promise 都成功完成(fulfilled)时完成
  • 或者只要有一个 Promise 失败(rejected)时就失败并带有第一个被拒绝的原因
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'foo');
});Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values);
});
// Expected output: Array [3, 42, "foo"]

.race

  • 接受一个包含多个 Promise 的数组
  • 返回一个新的 Promise,谁先执行完毕,谁的结果就决定race的结果
const promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 500, 'one');
});const promise2 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'two');
});Promise.race([promise1, promise2]).then((value) => {console.log(value);// Both resolve, but promise2 is faster
});
// Expected output: "two"

.any

  • 接受一个可迭代对象
  • 返回一个新的 Promise只要传入的 Promise 中有一个成功,并返回第一个兑现的值
  • 如果所有的 Promise 都失败,则返回一个失败的 Promise,并附带一AggregateError 错误
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));const promises = [promise1, promise2, promise3];Promise.any(promises).then((value) => console.log(value));// Expected output: "quick"

关于Promise的详细内容还有许多,本文仅做简略描述,请谅解

async与await (ES8/ES2017)

他的作用就是使你的promise代码看起来像同步一样

async

  • 用于声明一个异步函数
  • 异步函数默认返回一个 Promise 对象
  • 如果函数内部返回的是一个非 Promise 的值,它会被自动封装成 Promise.resolve(value)

await 

  • 用于等待一个异步操作(即 Promise)的完成
  • await 必须在 async 函数内部使用
  • 它会暂停代码执行,直到 Promise 的结果返回(成功或失败)

 传统写法

function fetchData() {return new Promise((resolve) => {setTimeout(() => resolve("数据加载完成"), 1000);});
}fetchData().then((result) => {console.log(result);return "下一步操作";}).then((nextResult) => {console.log(nextResult);}).catch((err) => {console.error(err);});

新式写法

async function fetchData() {return new Promise((resolve) => {setTimeout(() => resolve("数据加载完成"), 1000);});
}async function run() {try {const result = await fetchData();console.log(result);const nextResult = "下一步操作";console.log(nextResult);} catch (err) {console.error(err);}
}run();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62387.shtml

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

相关文章

应用案例丨坤驰科技双通道触发采集实时FFT数据处理系统

双通道触发采集实时FFT数据处理系统 应用案例 双通道采集,每路通道需要2GSPS的采样率,每2毫秒采集一次,每次采集数据量为65536*2 Sample。采集的信号频率满足奈奎斯特采样定律。采集数据后,每路通道的数据均做运算以及FFT实时处理…

OGRE 3D----3. OGRE绘制自定义模型

在使用OGRE进行开发时,绘制自定义模型是一个常见的需求。本文将介绍如何使用OGRE的ManualObject类来创建和绘制自定义模型。通过ManualObject,开发者可以直接定义顶点、法线、纹理坐标等,从而灵活地构建各种复杂的几何体。 Ogre::ManualObject 是 Ogre3D 引擎中的一个类,用…

如何用Excel做数据可视化自动化报表?

作为一个经常需要做数据报表的人,我最常用的工具是Excel,对于我来说用Excel处理繁琐冗杂的数据并不难,但是我发现身边很多人用Excel做的数据报表非常的耗时,而且最后的成品也是难以直视,逻辑和配色等都非常的“灾难”。…

结构型模式-组合模式

组合模式(Composite Pattern)是一种结构型设计模式,它通过将对象组合成树形结构来表示“部分-整体”的层次结构,从而使客户端对单个对象和组合对象的使用具有一致性。 适用场景 需要表示对象的层次结构:如文件系统、组…

HOW - React 状态模块化管理和按需加载(二) - jotai

目录 一、背景二、jotai 介绍2.1 基本介绍Jotai 的核心特点在现有项目中使用 Jotai 的场景 2.1 jotai 使用安装 Jotai基本使用方法1. 创建 Atom(状态单元)2. 使用 Atom3. 全局共享状态 与 Ant Design 和 Redux 的结合1. 替代局部状态的 Redux 实现2. 与 …

基于FPGA的SD NAND读写测试(图文并茂+源代码+详细注释)

本实验所使用的源代码已同步至个人主页的资源处,可供读者自行学习...... 什么是SD NAND? 1.SD NAND 卡介绍 SD NAND 卡是一种基于 NAND 闪存技术的存储设备,其外观和接口类似于标准的 SD 卡。它将 NAND 闪存芯片和必要的控制电路集成在一个小…

机器学习6-梯度下降法

梯度下降法 目的 梯度下降法(Gradient Descent)是一个算法,但不是像多元线性回归那样是一个具体做回归任务的算法,而是一个非常通用的优化算法来帮助一些机器学习算法求解出最优解的,所谓的通用就是很多机器学习算法都是用它,甚…

(0基础保姆教程)-JavaEE开课啦!--11课程(初识Spring MVC + Vue2.0 + Mybatis)-实验9

一、什么是Spring MVC? Spring MVC 是一个基于 Java 的 Web 框架,遵循 MVC 设计模式,用于构建企业级应用程序。它通过控制器(Controller)处理用户请求,模型(Model)处理业务逻辑,视图(View)展示数据,实现了请…

微前端-MicroApp

微前端即是由一个主应用来集成多个微应用(可以不区分技术栈进行集成) 下面是使用微前端框架之一 MicroApp 对 react微应用 的详细流程 第一步 创建主应用my-mj-app 利用脚手架 npx create-react-app my-mj-app 快速创建 安装 npm install --save rea…

python画图plt.close()一直闪烁

解决方法: import matplotlib matplotlib.use(Agg) # 设置后端为 Agg 在Matplotlib中,’后端’(backend)指的是用于实际绘制图形的底层图形库。Matplotlib支持多种后端,如’TkAgg’、’Qt5Agg’、’WXAgg’等&…

知识库助手的构建之路:ChatGLM3-6B和LangChain的深度应用

ChatGLM3-6B和LangChain构建知识库助手 安装依赖库 使用pip命令安装以下库: pip install modelscope langchain0.1.7 chromadb0.5.0 sentence-transformers2.7.0 unstructured0.13.7 markdown3.0.0 docx2txt0.8 pypdf4.2.0依赖库简介: ModelScope&a…

MySQL中的count函数

1. COUNT() 是什么? 在 MySQL 中,COUNT() 是一个聚合函数,用于统计结果集中行的数量。它常见的几种用法包括: COUNT(*):统计结果集中所有行的数量,包括包含 NULL 的行。COUNT(1):统计结果集中所…

shell(2)永久环境变量和字符串显位

shell(2)永久环境变量和字符串显位 声明! 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习…

基于pytorch使用仿真数据集来训练一个深度学习模型进行相位解包裹

使用 PyTorch 来训练一个深度学习模型进行相位解包裹是一种常见的方法。下面是一个详细的示例,展示如何生成仿真数据集并在 PyTorch 中训练模型。 1. 生成仿真数据集 首先,我们生成一些仿真数据集,包含多个包裹相位图和对应的解包裹相位图。…

使用 Python 的 pdfplumber 库高效解析 PDF 文件

使用 Python 的 pdfplumber 库高效解析 PDF 文件 PDF 文件是日常办公和数据处理中常见的文件格式,而 pdfplumber 是一个专为 PDF 文件解析设计的 Python 库,可以轻松提取文本、表格、图像等内容。本文将介绍 pdfplumber 的基本功能、使用方法&#xff0…

Java实现IP代理池

文章目录 Java实现IP代理池一、引言二、构建IP代理池1、代理IP的获取2、代理IP的验证1. 导入必要的库2. 设置代理IP和端口3. 发起HTTP请求4. 检查请求结果5. 完整的验证方法 注意事项 三、使用IP代理池四、总结 Java实现IP代理池 一、引言 在网络爬虫或者需要频繁请求网络资源…

微服务保护和分布式事务

文章目录 一、微服务保护1.1 微服务保护方案:1.1.1 请求限流:1.1.2 线程隔离:1.1.3 服务熔断: 1.2 Sentinel:1.2.1 介绍和安装:1.2.2 微服务整合: 1.3 请求限流:1.4 线程隔离&#x…

后端 Java发送邮件 JavaMail 模版 20241128测试可用

配置授权码 依赖 <dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api</artifactId><version>1.5.5</version> </dependency> <dependency><groupId>com.sun.mail</groupId><artifa…

MySQL安装与卸载(linux)

MySQL安装与卸载 MySQL8.0.26-安装1. 准备一台Linux服务器2. 下载Linux版MySQL安装包3. 上传MySQL安装包4. 创建目录,并解压5. 安装mysql的安装包6. 启动MySQL服务7. 查询自动生成的root用户密码8. 修改root用户密码9. 创建用户10. 并给root用户分配权限11. 重新连接MySQL MySQ…

LayaBox1.8.4实现自定义3DMesh

实现mesh的原理可参考我写的Unity中的自定义mesh的原理&#xff0c; 碰撞检测算法——分离轴算法在Unity中实现&#xff08;一&#xff09;_unity 自定义高性能碰撞检测方案-CSDN博客 实现可传入shader两张贴图的顶点声明如下&#xff1a; var vertexDeclarationLaya.Vertex…