先说说为什么要有异步这回事. JavaScript是单线程的, 也就是说它一次只能做一件事. 如果所有操作都同步执行, 遇到网络请求或者文件读取这种耗时的操作, 页面就会卡住不动, 用户体验直接爆炸. const data = fetchDataFromServer(); console.log(data); doSomethingElse(); 
所以JavaScript采用异步非阻塞的方式处理这类操作: 发起请求后不干等着, 而是继续执行后面的代码, 等请求完成后再来处理结果. 这就引出了我们最原始的处理方式——回调函数. function fetchData(callback) {  setTimeout(() => {    callback('数据到手啦!');  }, 1000);}
fetchData((data) => {  console.log(data); });
当多个异步操作需要顺序执行时, 代码就会变成这样: getUserInfo(userId, function(user) {  getOrders(user.id, function(orders) {    getOrderDetails(orders[0].id, function(details) {      getProductInfo(details.productId, function(product) {        console.log('最终结果:', product);      });    });  });});
这种代码的问题: 
1. 难以阅读和维护(金字塔形状)
2. 错误处理非常麻烦(要在每个回调里处理错误)
3. 无法使用return和throw
4. 无法使用for循环和try/catch
3) 回调的改进尝试
2.1 命名函数, 把匿名回调变成命名函数:
getUserInfo(userId, handleUser);
function handleUser(user) {  getOrders(user.id, handleOrders);}
function handleOrders(orders) {  getOrderDetails(orders[0].id, handleDetails);}
2.2 Async.js库, 提供series/parallel/waterfall等流程控制: async.waterfall([  function getUser(callback) {    getUserInfo(userId, callback);  },  function getOrders(user, callback) {    getOrders(user.id, callback);  }  ], function finalHandler(err, result) {  });
这些方案虽然有一定效果, 但都不够优雅. 直到Promise的出现. 
3.1 Promise直译就是"承诺", 它表示一个异步操作的最终完成或失败. Promise有三种状态: 
1. pending(进行中)
2. fulfilled(已成功)
3. rejected(已失败)
一旦状态改变就不会再变(要么成功要么失败).
const promise = new Promise((resolve, reject) => {    setTimeout(() => {    if (Math.random() > 0.5) {      resolve('成功数据');    } else {      reject(new Error('失败原因'));    }  }, 1000);});
promise  .then(data => {    console.log('成功:', data);  })  .catch(err => {    console.error('失败:', err);  });
3.2 Promise链式调用, 这是Promise最强大的地方: getUserInfo(userId)  .then(user => getOrders(user.id))  .then(orders => getOrderDetails(orders[0].id))  .then(details => getProductInfo(details.productId))  .then(product => {    console.log('最终结果:', product);  })  .catch(err => {    console.error('出错啦:', err);  });
对比之前的回调地狱, 这种链式调用: 
1. 扁平化, 可读性极佳
2. 错误处理统一(一个catch处理所有错误)
3. 可以使用return传递数据
4. 可以在then里throw error
Promise.all: 等所有Promise都成功. Promise.all([promise1, promise2, promise3])  .then(([result1, result2, result3]) => {      })  .catch(err => {      });
Promise.race:竞速, 第一个完成的Promise决定结果. Promise.race([fetchFromA(), fetchFromB()])  .then(firstResult => {      });
Promise.allSettled: 等所有Promise都完成(无论成功失败).Promise.allSettled([promise1, promise2])  .then(results => {    results.forEach(result => {      if (result.status === 'fulfilled') {        console.log('成功:', result.value);      } else {        console.log('失败:', result.reason);      }    });  });
虽然Promise很棒, 但还是有不足: 
1. 无法取消Promise.
2. 错误处理虽然比回调好, 但还是要用catch.
3. 多个Promise之间的数据共享不太方便.
4. 调试时堆栈信息不友好.
async/await是现代JavaScript异步编程的终极解决方案, 它让异步代码看起来和同步代码一样直观, 用起来更简单: async function fetchData() {  try {    const user = await getUserInfo(userId);    const orders = await getOrders(user.id);    const details = await getOrderDetails(orders[0].id);    console.log(details);  } catch (err) {    console.error(err);  }}
这代码看起来完全是同步的风格, 但实际上是异步执行的!
1) 如果返回非Promise值, 会自动包装成Promise.resolve(值)
2) 如果抛出异常, 返回Promise.reject(异常)
await只能在async函数中使用:
1) 普通函数中使用会报语法错误
2) 现代浏览器和Node.js的模块系统中支持顶层await
4.2 await解析
4.2.1 await的行为
async function example() {  const result = await somePromise;  console.log(result);}
这段代码实际上做了以下几件事:
1. 暂停example函数的执行
2. 等待somePromise完成
3. 如果Promise成功, 恢复执行并将结果赋值给result
4. 如果Promise失败, 抛出拒绝原因(可以用try/catch捕获)
4.2.2 await不一定要等Promise
虽然设计初衷是处理Promise, 但await可以等待任何值:
async function foo() {  const a = await 42;   const b = await someFunction(); }
4.2.3 错误处理机制
await的错误处理非常符合直觉, 可以用传统的try/catch: 
async function fetchData() {  try {    const data = await fetch('/api');    const json = await data.json();    console.log(json);  } catch (err) {    console.error('请求失败:', err);  }}
对比Promise的.catch(), 这种写法更接近同步代码的思维模式. 
五、常见使用方式
5.1 顺序执行: 
async function sequential() {  const user = await getUser();  const posts = await getPosts(user.id);  const comments = await getComments(posts[0].id);  return comments;}
5.2 并行执行: 
async function parallel() {  const [user, posts] = await Promise.all([    getUser(),    getPosts()  ]);  return { user, posts };}
5.3 循环中的await: 
async function processArray(array) {  for (const item of array) {    await processItem(item);  }}
async function processArrayParallel(array) {  await Promise.all(array.map(item => processItem(item)));}
5.4 await可以等待任何thenable对象: 
async function example() {  const result = await {    then(resolve) {      setTimeout(() => resolve('done'), 1000);    }  };  console.log(result); }
5.5 混合使用Promise和async/await: 
async function getUserPosts(userId) {  return fetchUser(userId)      .then(user => fetchPosts(user.id))    .then(posts => {      return asyncFunction(posts);     });}
阅读原文:原文链接
该文章在 2025/7/7 11:32:20 编辑过