Skip to content

async/await 到底做了什么

本质:Promise 的语法糖

asyncawait 是对 Promise .then() 链式调用的封装,让异步代码的书写方式和阅读方式都更接近同步代码。一个 async 函数始终返回 Promise,await 会等待右侧的 Promise 完成并直接拿到 resolve 的值。

javascript
function getUser() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ id: 1, name: '彤彤' });
    }, 500);
  });
}

function getPosts(userId) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve([{ id: 101, title: 'Promise 入门指南' }]);
    }, 500);
  });
}

function getComments(postId) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(['写得不错', '很有帮助']);
    }, 500);
  });
}

用 Promise 链式调用时,代码结构是 .then() 串联:

javascript
getUser()
  .then((user) => getPosts(user.id))
  .then((posts) => getComments(posts[0].id))
  .then((comments) => console.log(comments))
  .catch((err) => console.error('出错了', err));

换成 async/await 之后:

javascript
async function loadPageData() {
  try {
    const user = await getUser();
    const posts = await getPosts(user.id);
    const comments = await getComments(posts[0].id);
    console.log(comments);
  } catch (err) {
    console.error('出错了', err);
  }
}

loadPageData();

两段代码的运行时行为完全一致,但 async/await 版本的执行流程是一行接一行往下读的,不需要追踪 .then() 的链路。

如何处理结果和错误

使用 await 获取结果时直接拿到 resolve 的值,不需要在 .then() 的回调中处理:

javascript
async function run() {
  const user = await getUser(); // user 就是 resolve 的值
  console.log(user);
}

错误处理使用 try...catch,而不是 .catch()

javascript
function processOrder(orderId) {
  return new Promise((resolve, reject) => {
    if (orderId > 0) {
      resolve({ status: 'confirmed' });
    } else {
      reject('订单 ID 无效');
    }
  });
}

async function handleOrder() {
  try {
    const result = await processOrder(101);
    console.log('成功:', result); // 成功:{ status: 'confirmed' }
  } catch (err) {
    console.log('失败:', err);
  }
}

async function handleBadOrder() {
  try {
    const result = await processOrder(-1);
    console.log('成功:', result);
  } catch (err) {
    console.log('失败:', err); // 失败:订单 ID 无效
  }
}

三种方案的对比

回顾从原始回调到 async/await 的演进:

方案错误处理可读性适用场景
嵌套回调每层单独处理嵌套深,追踪困难历史代码维护
Promise + then.catch() 统一捕获链式调用,相对扁平需要 .then() 灵活组合
async/awaittry...catch 统一捕获像同步代码,直观流程明确、步骤顺序执行的场景

在需要精细控制并发(比如 Promise.allPromise.race 组合多个异步操作)时,.then() 的组合方式更有表达力。在纯粹的顺序执行场景中,async/await 的写法更简洁。