当前位置:  首页>> 技术小册>> 微信小程序全栈开发实战(上)

53 | 网络接口简介(四):Promise三个方法anyallrace的使用介绍

在微信小程序的全栈开发过程中,网络请求是不可或缺的一环,它连接着前端与后端的数据交互,是实现动态内容展示和交互功能的关键。而在处理异步网络请求时,JavaScript 的 Promise 对象为我们提供了一种优雅的方式来处理这些异步操作。本章节将深入介绍 Promise 对象的三个高级方法:Promise.any()Promise.all()Promise.race(),它们各自在特定的场景下能够极大地提升代码的可读性和效率。

一、Promise.all():并行执行,全部成功

Promise.all() 方法接收一个 promise 数组作为参数,并返回一个新的 promise 实例。只有当这个数组里的所有 promise 都成功完成时,返回的 promise 才会解决(resolve),并且它的解决值(resolve value)是一个数组,包含了所有 promise 的解决值,顺序与输入数组中的 promise 顺序一致。如果有任何一个 promise 失败(reject),则返回的 promise 会立即失败,且失败原因是第一个失败的 promise 的失败原因。

应用场景

  • 当你需要从多个不同的 API 获取数据,并且这些数据之间没有依赖关系,但你需要等待所有数据都加载完成后才能继续执行下一步操作时,Promise.all() 显得尤为适用。

示例代码

  1. function fetchUserData(userId) {
  2. return new Promise((resolve, reject) => {
  3. // 模拟异步请求
  4. setTimeout(() => {
  5. if (userId > 0) {
  6. resolve(`User ${userId} data`);
  7. } else {
  8. reject('Invalid user ID');
  9. }
  10. }, 1000);
  11. });
  12. }
  13. Promise.all([
  14. fetchUserData(1),
  15. fetchUserData(2),
  16. fetchUserData(3)
  17. ]).then(results => {
  18. console.log(results); // ["User 1 data", "User 2 data", "User 3 data"]
  19. }).catch(error => {
  20. console.error(error); // 如果有任何一个请求失败,将捕获错误
  21. });

二、Promise.race():竞争执行,第一个完成

Promise.race() 方法同样接收一个 promise 数组作为参数,但它与 Promise.all() 的行为截然不同。Promise.race() 返回一个新的 promise,这个 promise 会在数组中的任意一个 promise 解决(resolve)或拒绝(reject)时立即以相同的值被解决或拒绝。换句话说,它实现了“竞争”机制,哪个 promise 先完成(无论成功或失败),返回的 promise 就以该 promise 的结果作为自己的结果。

应用场景

  • 当有多个请求发送,但你只需要第一个返回的结果时,使用 Promise.race() 可以有效减少等待时间。
  • 超时处理,可以创建一个在指定时间后解决的 promise,与其他请求一起传递给 Promise.race(),以实现超时机制。

示例代码

  1. function fetchWithTimeout(userId, timeout) {
  2. return Promise.race([
  3. fetchUserData(userId), // 假设这是实际的请求函数
  4. new Promise((resolve, reject) => {
  5. setTimeout(() => reject('Request timed out'), timeout);
  6. })
  7. ]);
  8. }
  9. fetchWithTimeout(1, 500).then(data => {
  10. console.log(data); // 如果500ms内请求完成,则显示数据
  11. }).catch(error => {
  12. console.error(error); // 如果500ms内请求未完成,则显示超时信息
  13. });

三、Promise.any():并行执行,至少一个成功

Promise.any() 是 ES2020 引入的一个新方法,与 Promise.all() 类似,它也接收一个 promise 数组作为参数,并返回一个新的 promise。但不同的是,Promise.any() 等待的是数组中的任意一个 promise 成功解决(resolve),而不是全部。如果所有传入的 promise 都失败了,则返回一个新的 promise,该 promise 会被拒绝(reject),且拒绝原因是一个包含所有失败原因的 AggregateError(一个特殊的 Error 对象,用于表示多个错误)。

应用场景

  • 在多个备选服务源中请求数据,只要其中一个成功即可。
  • 尝试多种方法解决问题,只要有一种方法成功就停止其他尝试。

示例代码(注意:由于 Promise.any() 是较新的特性,确保你的运行环境支持 ES2020 或使用适当的 polyfill):

  1. Promise.any([
  2. fetchUserData(100).catch(() => null), // 假设这个用户ID无效,通过catch避免直接reject
  3. fetchUserData(2),
  4. fetchUserData(3)
  5. ]).then(result => {
  6. console.log(result); // 输出第一个成功的结果
  7. }).catch(error => {
  8. if (error instanceof AggregateError) {
  9. console.error('All requests failed:', error.errors); // 处理所有请求失败的情况
  10. } else {
  11. console.error('Unexpected error:', error);
  12. }
  13. });

在上述代码中,我们通过 .catch(() => null) 来处理可能失败的请求,防止它们影响 Promise.any() 的结果。这是因为 Promise.any() 会忽略那些被解决为 nullundefined 的 promise,只有当所有 promise 都以失败告终时,它才会被拒绝。

总结

Promise.all()Promise.race()Promise.any() 是处理并行异步操作时的强大工具,它们各自在不同的场景下发挥着重要作用。了解并熟练掌握这些方法的使用,对于提升微信小程序全栈开发的效率和代码质量至关重要。通过合理组合使用这些方法,你可以更灵活地处理复杂的异步逻辑,编写出既高效又易于维护的代码。


该分类下的相关小册推荐: