JS的promise以及promise链使用详解

JavaScript中Promise链错误处理的调试方法 JavaScript Promise链错误调试的核心在于显式捕获、全局兜底、工具链协同。通过结合.catch()监控及开发者工具(如Chrome DevTools),开发者可高效定位异步错误。实战建议对关键Promise链添加.finally()进行资源清理使用处理并行任务中的部分失败实现统一的错误分类与日志系统通过本文的代码示例与调试方法,开发者可构建健壮的异步JavaScript应用,显著降低因未处理Promise拒绝导致的线上故障风险。 阅读详情

异步操作通常都带着回调函数以便异步动作完成时操作,这种设计本身没什么问题,但是一旦出现了异步的嵌套就会让人陷入回调地狱,层层嵌套的操作让人看着眼花缭乱。Promise结构的出现就是专门帮助我们解决这个烦恼的,这一节我们就来看看promise的用法以及promise链。

Promise的基本结构

首先必须要理解,promise并不是一个具体的异步操作(例如Ajax或者setTimeout),而只是通过一种新的书写格式,将原来的异步操作和回调函数部分进行了解耦合,更容易让人理解。所以promise并不是异步操作,而只是对异步操作的重新包装。

解耦合之后的异步操作部分,可以理解为生产者,而异步操作的结果(不管成功或者失败)会被传递给一个或多个回调函数,可以理解为消费者。下面我们就分别来看看生产者和消费者的书写格式。

异步操作部分

就是新建一个Promise对象,基本书写格式如下

let promise = new Promise(function(resolve, reject) {
  // 异步操作的代码
});

创建promise的时候要传递一个函数进去,该函数包含的部分会被马上执行。注意函数的两个参数resolve和reject,是js规定好的两个回调函数,分别是当函数成功返回或者报错时候进行调用。所以函数的执行结果不需要return,而只能是下面两种中的一个

  • resolve(value) - 函数成功执行,传递value到下一步
  • reject(error) - 函数执行失败,传递error到下一步

如下图所示

1-promise.png

下面就是成功返回结果的例子

let prom = new Promise(function(resolve,reject){
		console.log(1);
		setTimeout(function(){
			console.log(2);
			resolve('Done')
		},2000)
});
console.log(3);

这里通过setTimeout模仿一个耗时2秒钟执行完成的异步动作。程序直接执行promise内的函数,所以先打印1,之后将异步操作交给专门的进程去处理,主进程继续向下执行,打印3,过了两秒打印2并且返回一个Done的结果给后面去使用。所以最后的打印顺序就是1、3、2。

如果将resolve('Done')改为reject(new Error("Whoops!"))就是返回一次失败的异步操作,其中的Error对象也可以供后面去使用。

这样就可以在异步操作中对结果做一个初步的判断,例如Ajax操作获取数据,如果数据符合预期就用resolve方法传递数据到下一步,否则就用reject方法传递错误到下一步。

只有第一次resolve或者reject才会生效

注意如果是像下面这样子,只会传递Done到下一步,后面的不管成功或者失败的返回都会被忽略

let promise = new Promise(function(resolve, reject) {
  resolve("done");

  reject(new Error("…")); // ignored
  setTimeout(() => resolve("…")); // ignored
});

resolve或者reject之后还是可以执行命令

函数中的return代表着函数返回,并不会继续向下执行。而和函数中return不同,promise中resolve或者reject并不会影响函数继续向下执行

let prom = new Promise(function(resolve,reject){
		console.log(1);
		setTimeout(function(){
			console.log(2);
			resolve('Done');
			console.log(4);
		},2000)
});
console.log(3);

上面的脚本会打印

1
3
2
4

并且,后面就会看到,4的打印要比后面的消费者处理Done要快,这涉及到js中的异步操作和事件循环逻辑,这里不展开了,我会专门写一篇博客来详细说明。

消费者

前面异步操作返回的结果,不管是成功或错误,都会传递到下一步的消费函数。要声明一个消费函数,可以用promise对象的.then、.catch或者是.finally方法。

then

then算是最常用的方法,格式如下

promise.then(
  function(result) { /* handle a successful result */ },
  function(error) { /* handle an error */ }
);

传递两个函数作为参数,第一个是异步操作resolve时执行,第二个是异步操作reject时执行。例如

let prom = new Promise(function(resolve,reject){
	console.log(1);
	setTimeout(function(){
		console.log(2);
		resolve('Done');
		// reject(new Error('Whoops'));
        console.log(4);
	},2000)
});
console.log(3);
prom.then(result=>console.log(result),error=>console.log(error));

此时会打印

1
3
2
4
Done

再次说明,为什么Done在4后面涉及到js的事件循环逻辑,这里不展开了,后面再专门写一篇来详细说明

因为是resolve,所以第一个函数被执行,如果换成reejct,就是第二个函数被执行。

如果只是对成功返回的结果感兴趣,可以只保留第一个函数

let prom = new Promise(function(resolve,reject){
	console.log(1);
	setTimeout(function(){
		console.log(2);
		resolve();
		// reject(new Error('Whoops'));
        console.log(4);
	},2000)
});
console.log(3);
prom.then(result=>console.log('Xiaofu'));

最后会打印

1
3
2
4
Xiaofu

注意我这里也顺便把resolve的参数去掉了,也就是说resolve和reject可以只传递一个成功或失败的信号,而不带任何内容到下一步。

catch

如果只是对失败的结果感兴趣,可以将then方法的第一个参数设置为null,或者使用catch方法

let prom = new Promise(function(resolve,reject){
	console.log(1);
	setTimeout(function(){
		console.log(2);
		// resolve();
		reject();
		console.log(4);
},2000)
});
console.log(3);
prom.then(()=>{console.log('Xiaofu')});
prom.catch(()=>{console.log('Oh no!')});

会打印

1
3
2
4
Oh no!
finally

和try{}catch{}语法一样,promise也有一个finally方法,不管promise的函数返回成功或者失败,finally都会被执行。其特别适合做一些善后的工作,例如记录操作结果进日志之类的。

Promise链

可以看到,promise的生产消费的结构可以非常直观地将异步操作展现出来。那么如果出现了回调函数的嵌套呢?这时候就需要用来promise链(promise chaining)了。

类似下面这样

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

promise链其实就是then方法的级联,前一个then方法中函数返回的结果会传递到下一个then方法。

  • 首先promise函数在一秒后resolve为1 (*)
  • 第一个then中函数被调用,打印1,并且返回2 (**)
  • 下一个then中函数被调用,打印上面then传递的2,并且返回4 (***)
  • 依次类推,最后的结果就是1->2->4

之所以能这样使用,是因为then方法返回的结果还是一个promise对象,而其函数return的值就是promise所resolve的内容。

注意,如果是对同一个promise对象多次使用then方法并不是promise链。

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

这样相当于对promise增加了3个消费者,所以最后只会弹出3个1。

用图形来表示的话,promise链中的数据流是这样的

2-chain.png

而作为对比,上面错误的使用数据流是这样的

3-wrong.png

像这种一个promise对象添加多个then方法的情况在实际使用中很少,往往是promise链这种回调函数的嵌套比较常见。

返回promise对象

在promise链中,then方法中的函数可以显示地去返回promise对象,如下

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});

这样写的返回结果和前面的例子一样,也是1->2->4,但是每次返回之间会隔着1秒钟的间隔。这样的好处就是我们可以进行多个异步操作的级联。

总结

总结下这节的知识点

  • promise本身不是异步操作,而只是异步操作的一种更直观的书写格式
  • promise对象在创建时候里面的函数会被马上执行,并且最终的结果是resolve或者reject的一种
  • resolve和reject的3个特性:只有第一个才有效,可以不带参数,之后的代码还会执行
  • 通过promise对象的then、catch和finally方法来使用resolve和reject传递的内容
  • 通过then方法的级联来实现promise链,还可以通过显示地返回promise对象来实现多个异步操作的级联
  • 需要注意的是对同一个promise对象的多次then方法并不是promise链

参考

  • promise - https://javascript.info/promise-basics
  • promise chaining - https://javascript.info/promise-chaining

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

JavaScript异步时序错误?Promise链的顺序验证工具 JavaScript异步时序错误与Promise链验证工具 本文系统探讨了JavaScript异步编程中Promise链的时序问题和验证方法。主要内容包括: 典型错误场景: 微任务(Promise)与宏任务(setTimeout)的调度差异导致的执行顺序错乱 Promise链中未被捕获的中间错误导致后续逻辑中断 时序验证工具集: 状态断言工具用于关键节点检查 任务队列监控工具模拟异步调度 Promise.allSettled实现并行Promise错误聚合 高级调试技巧: 递归实现严格顺序的异步任务队列 使用 阅读详情

相关推荐

JavaScript小技能:原型链的运作机制、Promise链

prototype 属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中。于是、等等成员,适用于任何继承自 Object() 的对象类型,包括使用构造器创建的实例。、,以及其他不在 prototype 对象内的成员,不会被继承自 Object() 的对象类型”所继承。对象的原型是每个实例上都有的属性,可以通过获得。和指向着同一个对象。函数也是一个对象类型,每个函数都有一个特殊的属性叫作原型(prototype)添加一些属性到 doSomething 的原型。.........

专注于计算机研发知识和资讯分享 1268

promise的链式用法详细

本文重点分析了promise的链式用法。 1 简介 本文介绍promise对象的then,catch,finally方法及链式用法。重点介绍了then的使用方式以及对链式调用的执行过程。 如果你对promise不是很了解,可以先查看 promise初级文章-在上一篇文章。 2 主要内容 •then的参数及执行逻辑•then的返回值•catch•finally•链式调用的逻辑 3 Promise实例的方法 在js中,对象会从它的构造器的原型对象中继承方法。例如: var arr ...

sqLeiQ的博客 8224

RU.EXE实用指南:从基础操作到高级调试技巧

本文是RU.EXE(RW Everything)的实用指南,详细介绍了这款硬件调试工具从基础操作到高级技巧的全过程。文章阐述了RU.EXE作为直接读写硬件寄存器、内存和PCI配置空间的强大工具,如何帮助硬件工程师和开发人员高效进行底层系统调试与故障排查,并强调了安全操作的重要性。

weixin_29228203的博客 278

promise打印顺序

Promise,打印顺序,事件循环

qq_44307861的博客 1274

关于VS2019调试问题:进程已退出,代码为-1073741819(已解决)

关于VS2019调试问题:进程已退出,代码为-1073741819(已解决) 详情:上一篇发了这个进程问题,在我翻阅了《c语言程序设计第四版》和《算法与数据结构》两本书对照代码加上调试终于找到了解决方法 解决方法: 首先找到项目的源文件右击找到属性 然后选择从生成中排除选择是! 重新生成解决方案,发现代码问题: 之前的代码: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include &lt

qq_51553982的博客 1万+

保姆级教程:在PX4 Gazebo仿真中为Iris无人机挂载Intel D435i深度相机(含完整配置流程)

本文提供在PX4 Gazebo仿真环境中为Iris无人机挂载Intel D435i深度相机的完整配置流程,涵盖环境准备、模型部署、插件安装及调试技巧。通过详细步骤和常见问题解决方案,帮助开发者快速搭建深度相机仿真环境,适用于无人机视觉开发与算法测试。

weixin_28688385的博客 335

Promise链

异步任务需要一个接一个的执行(如执行脚本),所以可以使用Promise链 new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 1000); }).then(function(result) { alert(result); return result * 2; }).then(function(result) { alert(result); // 2 return resu.

AnitaSun的博客 633

MCGS触摸屏数据记录与U盘导出配置全解析

在工业自动化现场,数据记录是设备运行状态分析与故障追溯的基础。HMI触摸屏作为人机交互核心,不仅承担实时监控任务,还负责过程数据的存储与导出。理解数据采集周期、存盘机制与存储介质的匹配原理,能帮助工程师高效配置数据记录功能。合理运用定时存盘、存盘组与U盘导出,可支撑设备趋势分析、报表生成及事故排查。本文以MCGS触摸屏为例,详解数据记录的完整组态流程,并汇总常见配置陷阱与排查思路,为现场调试与长期运维提供可落地的技术参考。

weixin_34253126的博客 459

深入理解Promise之一步步教你手写Promise构造函数

Promise是前端面试中笔记走重要的一个考点。如何真正的了解promise?我们不如自己动手,写一个可以拿来用的Promise.js。下面是循序递进的写法教学,本文的最后也有完整写法的代码可以借鉴,希望能够帮助大家!后面如果有机会会写一篇详解promise的博客,欢迎关注!

zxdznyy的博客 2249

【MUJOCO控制篇-2】控制一个简单的机械臂

本篇博客将逐步分析和解释如何通过Python代码使用MuJoCo库来控制一个机械臂模型。我们将从加载模型开始,逐步深入到PID控制器的实现,最后讨论如何实现轨迹跟踪功能。上期内容为如何建模一个简单的机械臂模型,本篇文章将基于上篇内容进行深入探讨如何实现一个简单的控制。

echo_Fangyb的博客 6745

Claude Code Skills 入门:内置技能与自定义技能开发

│ Skill 的特点 │1. 封装性:把复杂操作封装成简单命令2. 可复用:一次定义,随处使用3. 可定制:支持参数传入4. 可发现:通过 /skill-name 方式调用打个比方,如果说 Claude Code 的基础工具是「原材料」,那 Skills 就是「预制菜」——只需要简单加热(调用),就能得到成品(结果)。你可以创建自己的 Skill 来封装常用操作。Skill 支持参数,通过。

gaoxiang_120的专栏 670

使用forEach来输出延时的Promise会有问题,如何顺序输出?

看了b站前端周老师的视频,记录评论区的方法和自己的理解。 https://www.bilibili.com/video/BV1G5411o73g

m0_45873583的博客 1704

逻辑回归:利用Python实现二分类算法

通过使用Python编写的代码,我们可以训练逻辑回归模型并进行预测。接下来,我们将实现逻辑回归算法的训练函数。训练函数将接受训练数据集X和对应的标签y,以及学习率alpha和迭代次数num_iterations。训练完成后,我们可以使用训练得到的参数theta来进行预测。在这个例子中,我们有一个包含4个样本的训练数据集X,每个样本有两个特征。在这个例子中,如果预测概率大于等于0.5,则预测为类别1,否则预测为类别0。现在,我们可以使用训练函数来训练模型。根据给定的样本x_new,预测函数将返回相应的类别。

XlltEditor的博客 326

JavaScript Promise 和 Promise 链

文章目录创建一个 Promise示例 1:带有 Promise 的程序JavaScript Promise 链JavaScript then() 方法示例 2:用 then() 链接 PromiseJavaScript catch() 方法JavaScript Promise VS 回调JavaScript PromiseJavaScript 回调JavaScript finally() 方法JavaScript Promise 方法参考文档     在本教程中,您将借助示例了解 JavaScript pr

运维狗的备忘录 350

【CUDA Runtime】第一个“Hello World“程序

CUDA(Compute Unified Device Architecture)是 NVIDIA 提供的一个并行计算平台和编程模型,旨在通过利用 GPU 的强大计算能力来加速计算密集型应用。对于许多开发者而言,开始学习 CUDA 编程的第一步通常是编写一个简单的“Hello World”程序。尽管 CUDA 的实际应用远远超出一个简单的例子,但这个初步的示例能帮助开发者快速入门,理解基本的 CUDA 编程流程。

m0_62599305的博客 1504

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

前端知识点---promise链(javascript)

Promise 链(Promise chain)是指通过 Promise 对象的 then() 方法将多个异步操作按顺序串联起来,实现异步操作的顺序执行。每个 then() 方法都会返回一个新的 Promise,从而可以继续调用后续的 then() 方法。通过链式调用,可以避免回调地狱(callback hell),使代码更加简洁和可读。

2302_80171619的博客 1104

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

JavaScript-Promise链

有时候我们需要异步的执行一系列任务,Promise提供了很好的方式来实现这一操作。

qq_35652006的博客 472

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

JavaScript promise 链,并行promise

Promise 链promise 的 then 方法返回一个新的 promise:const promise = new Promise(resolve => setTimeout(resolve, 5000));promise // 5 seconds later .then(() => 2) // returning a value from a then callbac

gnimgnot 3991

When.js 是一个轻量级的 JavaScript Promise 库,用于处理异步操作

When.js 是一个轻量级的 JavaScript Promise 库,用于处理异步操作。版本 1.8.0 发布于 2014 年左右(具体日期为 2014 年 5 月 29 日),是 When.js 在其活跃维护期中的一个重要更新。该版本主要增强了对 Promises/A+ 规范的兼容性,修复了多个 Promise 链、错误传播和 `when.all()` / `when.race()` 等工具方法的边界问题,并提升了在 IE8+ 和现代浏览器中的稳定性与性能。

[Blog][Domain] programb.blog.youkuaiyun.com 384

从‘回调地狱’到‘Promise链’:手把手教你用Promise.resolve()重构老旧JavaScript代码

本文详细介绍了如何使用Promise.resolve()重构老旧JavaScript代码,从‘回调地狱’过渡到清晰的‘Promise链’。通过实战案例和技巧分享,帮助开发者提升异步代码的可维护性,涵盖统一接口、错误处理、性能优化等核心场景,特别适合处理遗留系统中的jQuery Deferred和嵌套回调问题。

weixin_30505225的博客 228

彻底解决Node.js异步调试痛点:Promise链追踪全攻略

你是否在调试Node.js异步代码时,遇到过Promise链报错却无法定位根源的问题?是否因为调用栈被截断而在回调地狱中迷失方向?本文将通过ndb(Node.js Debugger,基于Chrome DevTools的增强调试工具)提供的全链路追踪方案,帮助你精准定位异步错误,提升调试效率300%。读完本文你将掌握:Promise链断点设置技巧、异步调用栈完整还原、源码映射与实时编辑调试、多进程异

gitblog_00942的博客 453

如何串行执行Promise?

在JavaScript中,Promise对象通常用于表示异步操作的最终完成(或失败)及其结果值。如果你想串行执行多个Promise,即一个接一个地执行,你可以使用.then()链或者语法。

王铁柱666的博客 437

JavaScript 中断Promise链方法

文章目录1 Promise2 Promise链及如何终止2.1 现象2.2 原因2.3 解决方案3 参考链接: 1 Promise Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件,在ES6得到支持。 且具有以下特点: 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。 一...

Andy Tools 6360

异步编程进阶指南,彻底掌握JavaScript事件循环与Promise链

掌握JavaScript异步编程核心原理,深入解析事件循环机制与Promise链式调用。本javascript高级教程涵盖真实开发场景应用、常见陷阱规避及性能优化技巧,助你构建高效可靠的异步流程。彻底理解宏任务与微任务执行顺序,值得收藏。

QuickTrans的博客 719

JavaScript async/await 实战秘籍 异步编程技巧 + 避坑指南 秒杀 Promise then 链

其实 async/await 就是 Promise 的 “语法糖”,它没有创造新的异步机制,只是把 Promise 的 then 调用变成了编译器层面的自动处理。你写的 await getUserInfo (),本质上还是在调用 Promise 的 then 方法,只是不用你手动写了而已。说白了,Promise 解决了 “回调地狱”,而 async/await 解决了 “then 链的繁琐”,把异步逻辑写得跟顺序执行的代码一模一样。前面忘了提一句,async/await 虽然好用,但也不是万能的。

思索的涟漪,突破自我 600

《JavaScript异步操作链详解:如何统一处理同步与Promise函数》​

简单了解一下异步和同步操作的知识

2303_81135627的博客 621
上一篇: python3中各类变量的内存堆栈分配和函数传参区别实例详解
下一篇: Javascript的异步原理和事件循环图文详解
T型人小付
博客等级 码龄7年 433粉丝 210原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值