返回

Promise高手进阶之路:揭秘23个少有人知的高级技巧

前端

JavaScript Promise 高级用法:掌控异步编程

在现代 JavaScript 应用程序开发中,Promise 是处理异步操作和管理控制流的重要工具。掌握 Promise 的高级用法可以大幅提升代码的可读性、可维护性和效率。本文将深入探究 23 个高级 Promise 用法,帮助你成为 Promise 的专家。

1. 使用 Promise.all() 同时等待多个 Promise

当需要同时等待多个异步操作完成后再继续执行代码时,Promise.all() 派上了用场。该方法接受一个 Promise 数组作为参数,返回一个新的 Promise,该 Promise 在所有传入的 Promise 都成功解决或其中一个 Promise 失败时解决或拒绝。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 2 resolved');
  }, 2000);
});

Promise.all([promise1, promise2]).then((values) => {
  console.log(values); // ['Promise 1 resolved', 'Promise 2 resolved']
});

2. 使用 Promise.race() 等待第一个完成的 Promise

与 Promise.all() 相反,Promise.race() 会等待传入的 Promise 数组中的第一个 Promise 完成,无论它是成功还是失败。它非常适合处理竞争性操作,例如在超时后自动终止其他请求。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 2 resolved');
  }, 2000);
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value); // 'Promise 1 resolved'
});

3. 使用 Promise.resolve() 将值包装成 Promise

Promise.resolve() 用于将任何值包装成一个已解决的 Promise。这可以使非 Promise 值在 Promise 链中使用变得非常方便。

const value = 'Hello, world!';

const promise = Promise.resolve(value);

promise.then((value) => {
  console.log(value); // 'Hello, world!'
});

4. 使用 Promise.reject() 将错误包装成 Promise

类似地,Promise.reject() 用于将任何值包装成一个已拒绝的 Promise。这对于在处理异步操作时处理错误非常有用。

const error = new Error('Something went wrong!');

const promise = Promise.reject(error);

promise.catch((error) => {
  console.log(error); // Error: Something went wrong!
});

5. 使用 Promise.finally() 无论 Promise 是成功还是失败,都会执行的代码

Promise.finally() 允许你在 Promise 链的最后附加一个回调函数,无论 Promise 是成功解决还是拒绝。该回调函数总是被调用,无论前面的操作如何。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise resolved');
  }, 1000);
});

promise.finally(() => {
  console.log('This code will always run, regardless of the outcome of the promise.');
});

6. 使用 Promise.then() 链式调用多个 Promise

Promise.then() 方法允许你将 Promise 链接在一起,创建一个链式调用。这使你可以按顺序处理一系列异步操作,并且只有在上一个 Promise 成功解决后才能继续执行下一个 Promise。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 2 resolved');
  }, 2000);
});

promise1.then((value) => {
  console.log(value); // 'Promise 1 resolved'
  return promise2;
}).then((value) => {
  console.log(value); // 'Promise 2 resolved'
});

7. 使用 Promise.catch() 捕获 Promise 中的错误

Promise.catch() 方法用于捕获 Promise 链中的错误。它接受一个回调函数作为参数,该回调函数在 Promise 拒绝时被调用。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('Something went wrong!'));
  }, 1000);
});

promise.catch((error) => {
  console.log(error); // Error: Something went wrong!
});

8. 使用 Promise.allSettled() 等待所有 Promise 完成,无论它们是成功还是失败

Promise.allSettled() 方法类似于 Promise.all(),但它在所有传入的 Promise 完成后才解决,无论它们是成功还是失败。这对于处理一系列异步操作并获取每个操作的结果非常有用,即使其中一些操作失败。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('Something went wrong!'));
  }, 2000);
});

Promise.allSettled([promise1, promise2]).then((results) => {
  console.log(results);
  // [
  //   { status: 'fulfilled', value: 'Promise 1 resolved' },
  //   { status: 'rejected', reason: Error: Something went wrong! }
  // ]
});

9. 使用 Promise.any() 等待任何一个 Promise 完成,无论它是否成功

Promise.any() 方法等待传入的 Promise 数组中的任何一个 Promise 完成,无论它是成功还是失败。它非常适合处理竞争性操作,例如在超时后自动终止其他请求。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('Something went wrong!'));
  }, 2000);
});

Promise.any([promise1, promise2]).then((value) => {
  console.log(value); // 'Promise 1 resolved'
}).catch((error) => {
  console.log(error); // Error: Something went wrong!
});

10. 使用 Promise.timeout() 在指定时间内等待 Promise 完成

Promise.timeout() 方法接受一个 Promise 和一个超时时间作为参数。如果 Promise 在指定的时间内没有完成,它将被拒绝,并抛出一个 TimeoutError。这对于防止长时间运行的异步操作或在超时后自动终止请求非常有用。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise resolved');
  }, 1000);
});

Promise.timeout(promise, 2000).then((value) => {
  console.log(value); // 'Promise resolved'
}).catch((error) => {
  console.log(error); // Timeout: Promise did not resolve in 2000ms
});

结论

掌握 JavaScript Promise 的高级用法可以极大地提升你的异步编程技能。通过使用这些技巧,你可以轻松处理复杂的操作,管理控制流并构建健壮可靠的应用程序。

常见问题解答

  1. 什么是 Promise?

Promise 是 JavaScript 中用来处理异步操作和管理控制流的工具。它表示一个异步操作的最终结果,可以是已解决的(成功)或已拒绝的(失败)。

  1. Promise.all() 和 Promise.race() 的区别是什么?

Promise.all() 等待所有传入的 Promise 都完成,无论它们是成功还是失败,而 Promise.race() 等待传入的 Promise 数组中的第一个 Promise 完成,无论它是成功还是失败。

  1. 如何捕获 Promise 中的错误?

可以使用 Promise.catch() 方法来捕获 Promise 链中的错误。它接受一个回调函数作为参数,该回调函数在 Promise 拒绝时被调用。

  1. Promise.finally() 和 Promise.then() 有什么区别?

Promise.finally() 无论 Promise 是成功还是失败都会执行指定的回调函数,而 Promise.then() 仅在 Promise 成功解决时执行回调函数。

  1. 什么是 Promise 的链式调用?

Promise 的链式调用允许你将 Promise 链接在一起,创建一个按顺序执行一系列异步操作的链。你可以使用 Promise.then() 方法连接 Promise。