JavaScript 异步编程:理解 `await` 和 `Promise`


在现代 JavaScript 开发中,处理异步操作是较为常见的需求。但 Javascript 具有多种异步模型,本文主要研究在云函数开发中常用的 awaitPromise 两种异步范式,以便于更好地理解异步机制。

Promise 的基础知识

Promise 是一个表示异步操作结果的对象,它有三种状态:

  1. Pending(待定): 初始状态,异步操作还在进行中。
  2. Fulfilled(已完成): 异步操作成功完成,Promise 的结果可用。
  3. Rejected(已拒绝): 异步操作失败,Promise 的结果是错误信息。

创建一个 Promise:

const promise = new Promise((resolve, reject) => {
  // 模拟异步操作
  setTimeout(() => {
    const success = true; // 模拟成功或失败
    if (success) {
      resolve("Operation succeeded");
    } else {
      reject("Operation failed");
    }
  }, 1000);
});

处理 Promise 的结果:

promise
  .then((result) => {
    console.log(result); // 输出: "Operation succeeded"
  })
  .catch((error) => {
    console.error(error); // 输出: "Operation failed"
  });

async 和 await 的作用

asyncawait 是现代 JavaScript 用来简化异步编程的语法糖。它们使异步代码看起来像同步代码,使得处理异步操作更为直观。

定义 async 函数:

一个 async 函数总是返回一个 Promise。如果函数内有返回值,它会被自动包装为 Promise.resolve();如果抛出异常,则会被包装为 Promise.reject()

async function fetchData() {
  return "Data fetched";
}

使用 await:

await 用来暂停 async 函数的执行,直到 Promise 被解决或拒绝。它可以让异步操作的代码更像同步代码,易于阅读和维护。

async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

示例:

async function processFiles() {
  try {
    console.log('Start processing files');

    const file1 = await fetchData('/path/to/file1');
    console.log('File 1:', file1);

    const file2 = await fetchData('/path/to/file2');
    console.log('File 2:', file2);

    const file3 = await fetchData('/path/to/file3');
    console.log('File 3:', file3);

    console.log('All files processed');
  } catch (error) {
    console.error('Error processing files:', error);
  }
}

processFiles();

Promise 的静态方法

  • Promise.resolve(value):

    • 返回一个以给定值解析的 Promise。如果值是一个 Promise,则返回这个 Promise
    Promise.resolve('Success').then(console.log);
  • Promise.reject(reason):

    • 返回一个以给定拒绝原因拒绝的 Promise
    Promise.reject('Error').catch(console.error);
  • Promise.all(iterable):

    • 接受一个可迭代对象(如数组),其中的每个元素都是 Promise
    • 返回一个新的 Promise,在所有输入的 Promise 完成后解析。
    • 如果任何 Promise 被拒绝,返回的 Promise 也会被拒绝。
    Promise.all([p1, p2, p3])
      .then(results => console.log(results))
      .catch(error => console.error(error));
  • Promise.allSettled(iterable):

    • Promise.all 类似,但不管所有 Promise 的状态如何,都返回一个 Promise
    • 解析的值是一个数组,每个元素都是一个对象,表示每个 Promise 的状态和结果。
    Promise.allSettled([p1, p2, p3])
      .then(results => results.forEach(result => console.log(result)));
  • Promise.any(iterable):

    • 接受一个可迭代对象,其中的每个元素都是 Promise
    • 返回一个新的 Promise,在第一个成功的 Promise 解决时解析。
    • 如果所有 Promise 都被拒绝,则返回一个 AggregateError
    Promise.any([p1, p2, p3])
      .then(result => console.log(result))
      .catch(error => console.error(error));
  • Promise.race(iterable):

    • 接受一个可迭代对象,其中的每个元素都是 Promise
    • 返回一个新的 Promise,在第一个 Promise 解决或拒绝时解析或拒绝。
    Promise.race([p1, p2, p3])
      .then(result => console.log(result))
      .catch(error => console.error(error));

Promise 的组合

  • .finally():
    • Promise 被解决或拒绝后执行,无论结果如何都会执行 finally 中的代码。
    • 用于清理操作,例如关闭资源或重置状态。
    promise
      .then(result => console.log(result))
      .catch(error => console.error(error))
      .finally(() => console.log('Operation completed'));

参考

Comments

Leave a comment