概述
Promise 对象表示异步操作的最终完成(或失败)及其结果值。
Promise 始终处于以下状态之一:
- 待处理:初始状态,既未实现也未拒绝。
- 已实现:操作已成功完成。
- 已拒绝:操作失败。
与“旧式”回调不同,使用 Promises 具有以下约定:
- 在当前事件循环完成之前,不会调用回调函数。
- 即使异步操作完成(成功或失败),之后通过 then() 添加的回调仍将被调用。
- 可以通过多次调用 then() 来添加多个回调,它们将按照添加的顺序执行。
Promises 的典型特征是链接。
一般用法
1.Promise.all([])
当数组中的所有 Promise 实例都成功时,它会按请求的顺序返回成功结果数组。如果任何 Promise 失败,它将进入失败回调。
2. Promise.allSettled([])
执行不会失败;它返回与输入数组中每个 Promise 实例的状态相对应的数组。
3. Promise.any([])
如果输入数组中的任何 Promise 满足条件,则返回的实例将变为满足条件并返回第一个满足条件的 Promise 的值。如果所有 Promise 均被拒绝,则将变为拒绝条件。
4. Promise.race([])
只要数组中的任何 Promise 改变状态,race 方法的状态就会随之改变;第一个改变的 Promise 的值将传递给 race 方法的回调。
抛出异常不会改变竞争状态;它仍然由 p1 决定。
高级用法
以下是 9 种高级用法,可帮助开发人员更高效、更优雅地处理异步操作。
1.并发控制
使用 Promise.all 允许并行执行多个 Promises,但要控制同时请求的数量,您可以实现并发控制功能。
2. Promise 超时
有时,可能希望 Promise 在特定时间范围内未解析时自动拒绝。这可以按如下方式实现。
3. 取消 Promises
原生 JavaScript Promises 无法取消,但你可以通过引入可控中断逻辑来模拟取消。
4. Promise 数组的顺序执行
有时您需要按顺序执行一系列 Promise,确保前一个异步操作完成后再开始下一个操作。
5. Promise 的重试逻辑
当 Promise 因临时错误而被拒绝时,您可能希望重试其执行。
6. 确保 Promise 仅解析一次
在某些情况下,您可能希望确保 Promise 仅解析一次,即使多次调用 resolve。
7. 使用 Promises 代替回调
Promises 通过替代回调函数,提供了一种更标准化、更方便的方式来处理异步操作。
8. 动态生成 Promise 链
在某些情况下,您可能需要根据不同的条件动态创建一系列 Promise 链。
9. 使用 Promises 实现简单的异步锁
在多线程环境中,可以使用 Promises实现简单的异步锁,确保每次只有一个任务可以访问共享资源。
这段代码不断创建和解析 Promise,实现了一个简单的 FIFO 队列,确保只有一个任务可以访问共享资源。
lock 变量表示当前是否有任务正在执行,始终指向正在进行的任务的 Promise。
acquireLock 函数请求执行权限并创建一个新的 Promise 以等待当前任务完成。
结论
Promise 是现代 JavaScript 异步编程不可或缺的一部分。
掌握它们的高级技巧将大大提高开发效率和代码质量。通过上述各种方法,开发人员可以更自信地处理复杂的异步场景,编写更易读、更优雅、更健壮的代码。