JavaScript 异步处理

Promise 和 Async/Await 都是 JavaScript 中处理异步操作的机制,但它们有不同的语法特点和适用场景。

下面通过一个业务逻辑来进行比较。
这个业务场景是:依次调用3个API,获取用户数据→获取订单数据→更新用户活跃时间,并处理可能的错误。

语法比较

Promise 写法:👇

function getUserAndUpdateActivity(userId) {
  return fetchUser(userId)
    .then((user) => {
      console.log("User data:", user);
      return fetchOrders(user.id);
    })
    .then((orders) => {
      console.log("User orders:", orders);
      return updateLastActive(userId);
    })
    .then(() => {
      console.log("User activity updated");
      return "All operations completed";
    })
    .catch((error) => {
      console.error("Error in operation:", error);
      throw error; // 可以重新抛出或处理错误
    });
}

// 使用示例
getUserAndUpdateActivity(123)
  .then((finalResult) => console.log(finalResult))
  .catch((err) => console.error("Final error:", err));

Async/Await 写法:👇

async function getUserAndUpdateActivity(userId) {
  try {
    const user = await fetchUser(userId);
    console.log("User data:", user);

    const orders = await fetchOrders(user.id);
    console.log("User orders:", orders);

    await updateLastActive(userId);
    console.log("User activity updated");

    return "All operations completed";
  } catch (error) {
    console.error("Error in operation:", error);
    throw error; // 可以重新抛出或处理错误
  }
}

// 使用示例(与Promise版本相同)
getUserAndUpdateActivity(123)
  .then((finalResult) => console.log(finalResult))
  .catch((err) => console.error("Final error:", err));

对比分析

async/await 是 Promise 之上的语法糖。它为编写异步代码提供了一种更简洁的方法,使其更易于阅读和编写。使用 async/await,可以编写看起来与同步代码相似的异步代码,而且它在引擎盖下使用了 Promise。

方面 Promise.then() async/await
代码结构 横向延伸,链式调用 纵向延伸,类似同步代码
可读性 嵌套层次多时较难阅读 顺序执行,逻辑清晰
错误处理 .catch() 处理整个链的错误 try-catch 块可以精确控制错误范围
变量共享 需要串联变量(通过 return 传递) 可以在同一作用域共享变量
调试体验 调试器难以跟踪then链的执行流程 可以像同步代码一样逐行调试
并行操作 需要 Promise.all 显式处理 可以结合 Promise.all 使用
返回结果 必须显式 return 值(否则传给then的是undefined) 自动包装为 Promise

并行优化版本

Promise 写法:👇

const fetchInParallel = (userId: number): Promise<[User, Order[]]> => {
  // 同时发起多个请求
  const userPromise: Promise<User> = fetchUser(userId);
  const ordersPromise: Promise<Order[]> = fetchOrders(userId);

  // 使用 Promise.all 并行等待
  return Promise.all([userPromise, ordersPromise]).then(([user, orders]) => {
    console.log(`并行获取结果: ${user.name}${orders.length} 个订单`);
    return [user, orders]; // 返回元组类型
  });
};

// 使用示例
fetchInParallel(123).then(([user, orders]) => {
  console.log("最终数据:", user, orders);
});

Async/Await 写法:👇

const optimizedFlow = async (userId: number): Promise<[User, Order[]]> => {
  try {
    const [user, orders] = await Promise.all([
      fetchUser(userId),
      fetchOrders(userId), // 假设不需要等待用户数据
    ]);

    await updateLastActive(userId);
    return [user, orders]; // 返回元组类型
  } catch (error) {
    console.error("Parallel flow failed:", error);
    throw error;
  }
};

// 使用示例
optimizedFlow(123).then(([user, orders]) => {
  console.log("最终数据:", user, orders);
});

JavaScript 异步处理
http://guoguo.host/blog/p/62f72e62.html
作者
Guoguo
发布于
2025年1月2日
许可协议