JavaScript的 Promise,then,catch,finally,async,await 笔记250810

81 阅读37分钟

JavaScript的 Promise,then,catch,finally,async,await 笔记250810

JavaScript 异步编程全面指南:Promise 与 async/await

一、Promise 核心概念

Promise 是 JavaScript 处理异步操作的基础,它表示一个异步操作的最终完成(或失败)及其结果值。

     基本结构

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (/* 成功 */) {
    resolve(value); // 状态变为 Fulfilled
  } else {
    reject(error); // 状态变为 Rejected
  }
});

     三种状态

  1. Pending(进行中):初始状态
  2. Fulfilled(已成功):操作成功完成
  3. Rejected(已失败):操作失败
stateDiagram-v2
    [*] --> Pending
    Pending --> Fulfilled : resolve()
    Pending --> Rejected : reject()
    Fulfilled --> [*]
    Rejected --> [*]

二、Promise 链式方法

     1. .then() - 处理成功状态

promise.then(
  result => console.log(result), // 成功处理
  error => console.error(error)  // 可选错误处理
);

     2. .catch() - 处理错误

promise
  .then(result => process(result))
  .catch(error => console.error('捕获错误:', error));

     3. .finally() - 最终处理

promise
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log('操作完成'));

三、async/await 语法糖

async/await 是基于 Promise 的语法糖,使异步代码更易读、更同步化。

     1. async 函数

async function fetchData() {
  return '数据'; // 自动包装为 Promise.resolve('数据')
}

     2. await 表达式

async function getUser() {
  try {
    const response = await fetch('/api/user');
    const user = await response.json();
    return user;
  } catch (error) {
    console.error('获取用户失败:', error);
    throw error;
  }
}

四、Promise 与 async/await 互转

     Promise → async/await

// Promise 链
function getData() {
  return fetchData()
    .then(processData)
    .catch(handleError);
}

// async/await 等价形式
async function getData() {
  try {
    const data = await fetchData();
    return processData(data);
  } catch (error) {
    return handleError(error);
  }
}

     async/await → Promise

// async/await 形式
async function loadResources() {
  const [res1, res2] = await Promise.all([fetchA(), fetchB()]);
  return { res1, res2 };
}

// Promise 等价形式
function loadResources() {
  return Promise.all([fetchA(), fetchB()])
    .then(([res1, res2]) => ({ res1, res2 }));
}

五、错误处理对比

     Promise 方式

fetchData()
  .then(process)
  .then(save)
  .catch(error => console.error('链中任何错误:', error));

     async/await 方式

async function processData() {
  try {
    const data = await fetchData();
    const processed = await process(data);
    await save(processed);
  } catch (error) {
    console.error('捕获错误:', error);
  } finally {
    console.log('清理资源');
  }
}

六、并行执行模式

     1. Promise.all()

Promise.all([fetchUser(), fetchOrders()])
  .then(([user, orders]) => renderUI(user, orders))
  .catch(error => console.error('任一请求失败:', error));

     2. async/await 并行

async function loadDashboard() {
  const [user, orders] = await Promise.all([
    fetchUser(), 
    fetchOrders()
  ]);
  
  return { user, orders };
}

     3. Promise.race()

Promise.race([
  fetchWithTimeout('/api', 5000),
  timeout(3000) // 3秒超时
])
  .then(data => console.log('第一个完成的结果:', data))
  .catch(error => console.error('错误或超时:', error));

七、最佳实践与模式

     1. 避免回调地狱

// 回调地狱
getUser(userId, (user) => {
  getProfile(user.id, (profile) => {
    saveProfile(profile, () => {
      // 更多嵌套...
    }, handleError);
  }, handleError);
}, handleError);

// Promise 改进
getUser(userId)
  .then(user => getProfile(user.id))
  .then(profile => saveProfile(profile))
  .catch(handleError);

     2. 合理使用 async/await

// 错误:顺序执行独立操作
async function slowProcess() {
  const a = await getA(); // 等待A完成
  const b = await getB(); // 再开始B(不必要等待)
  return a + b;
}

// 正确:并行执行
async function fastProcess() {
  const [a, b] = await Promise.all([getA(), getB()]);
  return a + b;
}

     3. 错误处理策略

// 局部错误处理
async function updateUser(user) {
  try {
    await validateUser(user);
  } catch (error) {
    return { error: '验证失败' };
  }
  
  // 全局错误处理
  try {
    await saveUser(user);
    return { success: true };
  } catch (error) {
    logError(error);
    throw error;
  }
}

八、常见误区与解决方案

     1. 忘记 await

async function process() {
  const data = fetchData(); // 错误:缺少await
  // data是Promise对象,不是实际数据
}

     2. 错误处理遗漏

// 危险:未处理错误
async function criticalTask() {
  await criticalOperation();
}

// 安全:添加错误处理
async function safeTask() {
  try {
    await criticalOperation();
  } catch (error) {
    logError(error);
    throw error;
  }
}

     3. 不必要的 async

// 不必要的 async
async function getConfig() {
  return { setting: 'value' }; 
  // 等同于 return Promise.resolve({ setting: 'value' })
}

// 更简洁
function getConfig() {
  return { setting: 'value' };
}

九、高级模式

     1. 异步生成器

async function* asyncGenerator() {
  let i = 0;
  while (i < 3) {
    await sleep(1000);
    yield i++;
  }
}

(async () => {
  for await (const num of asyncGenerator()) {
    console.log(num); // 0, 1, 2 (每秒输出)
  }
})();

     2. 取消异步操作

function cancellableFetch(url) {
  const controller = new AbortController();
  
  const promise = fetch(url, {
    signal: controller.signal
  });
  
  return {
    promise,
    cancel: () => controller.abort()
  };
}

// 使用
const { promise, cancel } = cancellableFetch('/api/data');
setTimeout(cancel, 5000); // 5秒后取消

     3. 重试机制

async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (err) {
      if (i === retries - 1) throw err;
      await sleep(1000 * (i + 1)); // 指数退避
    }
  }
}

十、总结对比

特性Promiseasync/await
可读性链式调用,嵌套复杂类似同步代码,直观清晰
错误处理.catch() 方法try/catch 结构
调试链式调用调试困难可直接断点调试
流程控制.then() 链式控制使用标准控制结构
并行处理Promise.all()await Promise.all()
返回值总是返回 Promise总是返回 Promise

     何时选择哪种方式?

  • 简单链式操作:Promise 更简洁
  • 复杂业务逻辑:async/await 更易维护
  • 并行多个请求:Promise.all + await
  • 错误处理复杂:async/await + try/catch
  • 事件处理程序:Promise 链更合适

     终极建议

async function optimalApproach() {
  // 并行执行
  const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
  
  // 顺序处理
  const processed = await processData(data1);
  
  // 后台操作(无需等待)
  sendAnalytics(processed).catch(handleAnalyticsError);
  
  return { data2, processed };
}

掌握 Promise 和 async/await 是现代 JavaScript 开发的必备技能。理解它们的核心概念、转换关系和适用场景,能让你编写出更健壮、可维护的异步代码。

















1️⃣ 参考 1

JavaScript 的异步处理经历了从回调函数到 Promise,再到 async/await 的演进。以下是核心概念详解:


1. Promise(承诺) 表示异步操作的最终完成或失败及其结果值。

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求)
  if (success) resolve(value) // 成功状态
  else reject(error)          // 失败状态
})

     状态变化

  1. pending(进行中)→ fulfilled(已成功)
  2. pending(进行中)→ rejected(已失败)
    ⚠️ 状态一旦改变不可逆

2. .then() 处理 Promise 成功状态,返回新 Promise 实现链式调用。

promise
  .then(value => {
    console.log("成功:", value)
    return newValue // 传递给下一个 then
  })

3. .catch() 捕获链式调用中任意位置的错误(推荐替代 .then 的第二个参数)

promise
  .then(step1)
  .then(step2)
  .catch(error => {
    console.error("捕获所有错误:", error)
  })

4. .finally() 无论成功/失败必然执行,适用于清理操作

promise
  .then(handleSuccess)
  .catch(handleError)
  .finally(() => {
    console.log("无论结果如何都会执行")
    // 例如隐藏加载动画
  })

5. async/await(语法糖)      async 函数

  • 总是返回 Promise
  • 内部可用 await
async function fetchData() {
  return "data" // 等价于 Promise.resolve("data")
}

     await

  • 暂停 async 函数执行,等待 Promise 解决
  • 只能用在 async 函数中
async function getUser() {
  try {
    const response = await fetch('/api/user') // 等待 Promise 解决
    const data = await response.json()        // 再次等待
    return data
  } catch (error) {
    console.error("请求失败:", error)
  }
}

关键对比表

特性Promise.then()async/await
可读性链式调用,可能嵌套类同步代码,线性执行
错误处理.catch()then 的第二个参数try/catch
调试链式调用调试困难可像同步代码断点调试
返回值总是返回 Promiseasync 函数总返回 Promise
并行请求Promise.all()await Promise.all([...])

最佳实践      1. 并行优化(避免顺序等待)

// ✅ 正确:并行请求
async function fetchAll() {
  const [user, posts] = await Promise.all([
    fetch('/user'),
    fetch('/posts')
  ])
}

// ❌ 低效:顺序等待
async function slowFetch() {
  const user = await fetch('/user')   // 等待完成
  const posts = await fetch('/posts') // 才开始
}

     2. 错误处理统一

// 使用 catch 处理 async 函数错误
fetchData()
  .then(data => process(data))
  .catch(error => handleError(error)) // 捕获 async 函数中的错误

     3. 避免 await 滥用

// ❌ 不必要的 await
async function update(data) {
  return await api.update(data) 
  // 等效于:return api.update(data)
}

// ✅ 直接返回 Promise
async function update(data) {
  return api.update(data)
}

执行顺序经典题

console.log(1)

setTimeout(() => console.log(2), 0)

Promise.resolve()
  .then(() => console.log(3))
  .then(() => console.log(4))

async function run() {
  console.log(5)
  await Promise.resolve()
  console.log(6)
}
run()

console.log(7)

// 输出顺序:1 → 5 → 7 → 3 → 6 → 4 → 2

解析

  1. 同步代码:1, 5, 7
  2. 微任务(Promise/await):3, 6, 4
  3. 宏任务(setTimeout):2

📌 事件循环优先级:同步代码 > 微任务 > 宏任务

掌握这些核心概念,能让你在回调地狱、Promise 链和同步式异步代码之间灵活选择!

















2️⃣ 参考 2

JavaScript 异步编程全面解析:Promise 与 async/await

一、Promise 核心概念

Promise 是 JavaScript 处理异步操作的核心对象,表示一个异步操作的最终完成(或失败)及其结果值。

     Promise 的生命周期

  • Pending:初始状态,操作未完成
  • Fulfilled:操作成功完成
  • Rejected:操作失败

     创建 Promise

const myPromise = new Promise((resolve, reject) => {
  // 异步操作(如 API 调用、定时器等)
  if (/* 操作成功 */) {
    resolve('成功结果'); // 状态变为 Fulfilled
  } else {
    reject(new Error('错误信息')); // 状态变为 Rejected
  }
});

二、Promise 方法链

     1. .then() - 处理成功状态

myPromise.then(
  result => {
    console.log('成功:', result);
    return result + '处理';
  }
);

     2. .catch() - 处理失败状态

myPromise.catch(
  error => {
    console.error('失败:', error.message);
    return '默认值';
  }
);

     3. .finally() - 最终清理

myPromise.finally(() => {
  console.log('无论成功失败都会执行');
});

     完整链式调用示例

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log('数据:', data);
    return processData(data);
  })
  .catch(error => {
    console.error('请求失败:', error);
    return getCachedData();
  })
  .finally(() => {
    console.log('请求处理完成');
  });

三、async/await 语法糖

async/await 是基于 Promise 的语法糖,让异步代码看起来像同步代码。

     1. async 函数

async function fetchData() {
  // 函数始终返回 Promise
  return '数据';
}

// 等价于
function fetchData() {
  return Promise.resolve('数据');
}

     2. await 表达式

async function getUser() {
  try {
    const response = await fetch('/api/user'); // 暂停执行直到 Promise 完成
    const data = await response.json(); // 再次等待
    return data;
  } catch (error) {
    console.error('获取用户失败:', error);
  }
}

四、Promise 与 async/await 对比

     相同异步操作的不同写法

// Promise 写法
function loadData() {
  fetch('/api/data')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
}

// async/await 写法
async function loadData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

     错误处理对比

// Promise 错误处理
fetchData()
  .then(handleSuccess)
  .catch(handleError); // 捕获所有错误

// async/await 错误处理
async function main() {
  try {
    const result = await fetchData();
    handleSuccess(result);
  } catch (error) {
    handleError(error);
  }
}

五、高级用法与最佳实践

     1. 并行执行多个异步操作

// 使用 Promise.all
async function fetchAll() {
  const [user, posts] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/posts')
  ]);
  
  // 继续处理结果...
}

// 使用 Promise.allSettled(需要所有结果)
const results = await Promise.allSettled([
  fetchResource1(),
  fetchResource2()
]);

     2. 异步循环处理

// 顺序执行
async function processArray(array) {
  for (const item of array) {
    await processItem(item); // 逐个等待完成
  }
}

// 并行执行
async function processArrayParallel(array) {
  await Promise.all(array.map(item => processItem(item)));
}

     3. 错误处理模式

// 方式1:try/catch
async function safeFetch() {
  try {
    return await fetch('/api/data');
  } catch (error) {
    return null;
  }
}

// 方式2:Promise.catch
async function safeFetch() {
  return fetch('/api/data').catch(() => null);
}

// 方式3:辅助函数
function to(promise) {
  return promise
    .then(data => [null, data])
    .catch(error => [error, null]);
}

async function main() {
  const [err, data] = await to(fetch('/api/data'));
  if (err) {
    // 处理错误
  }
}

六、常见陷阱与解决方案

     1. 忘记 await

async function example() {
  const promise = fetchData(); // 缺少 await → 得到 Promise 对象
  console.log(promise); // 输出: Promise {<pending>}
  
  // 正确
  const result = await fetchData();
}

     2. 循环中的 await 误用

// 低效:顺序执行
for (const url of urls) {
  await fetch(url); // 每次等待
}

// 高效:并行执行
const promises = urls.map(url => fetch(url));
await Promise.all(promises);

     3. 未处理的 Promise 拒绝

async function dangerous() {
  throw new Error('未捕获');
}

// 解决方案1:添加 catch
dangerous().catch(console.error);

// 解决方案2:在 async 函数中使用 try/catch
async function safeCall() {
  try {
    await dangerous();
  } catch (err) {
    // 处理错误
  }
}

七、浏览器与 Node.js 支持

  • Promise:所有现代浏览器(包括 IE11)和 Node.js 0.12+
  • async/await
    • 浏览器:Chrome 55+, Firefox 52+, Safari 10.1+, Edge 15+
    • Node.js:7.6+(建议使用 10.0+ 版本)

总结对比表

特性Promiseasync/await
语法链式调用(.then/.catch)类似同步代码
错误处理.catch() 方法try/catch 块
可读性中等(回调金字塔风险)高(线性执行)
调试较困难(匿名函数)容易(标准调用栈)
返回值必须返回 Promise自动包装为 Promise
并行处理Promise.all()Promise.all() + await
循环处理需要 Promise 链for 循环 + await

最佳实践建议

  1. 新项目优先使用 async/await
  2. 复杂异步逻辑使用 Promise 组合方法(all、race 等)
  3. 始终处理可能的错误(try/catch 或 .catch)
  4. 避免不必要的顺序等待,尽可能并行化
  5. 使用 lint 规则防止忘记 await(如 ESLint 的 require-await)

掌握 Promise 和 async/await 的组合使用,可以让你编写出既高效又易读的异步 JavaScript 代码,显著提升开发体验和应用性能。

















3️⃣ 参考 3

在 JavaScript 中,Promise 和 async/await 是处理异步操作的核心机制。下面我将系统化地解释这些概念,并提供使用示例:

一、Promise 核心概念 Promise 是一个表示异步操作最终完成或失败的对象,包含三种状态:

  • Pending(进行中):初始状态
  • Fulfilled(已成功):操作成功完成
  • Rejected(已失败):操作失败

     创建 Promise:

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  setTimeout(() => {
    const success = Math.random() > 0.5;
    success ? resolve("Success!") : reject("Error occurred");
  }, 1000);
});

二、Promise 方法链      1. .then() - 处理成功状态

promise.then(result => {
  console.log(result); // "Success!"
});

     2. .catch() - 处理失败状态

promise.catch(error => {
  console.error(error); // "Error occurred"
});

     3. .finally() - 无论成功失败都会执行

promise.finally(() => {
  console.log("Operation completed");
});

     完整链式调用示例:

fetch("/api/data")
  .then(response => response.json())
  .then(data => processData(data))
  .catch(error => handleError(error))
  .finally(() => cleanUp());

三、async/await 语法糖 async/await 是基于 Promise 的语法糖,让异步代码更像同步代码:

     1. async 函数

  • 总是返回 Promise
  • 允许在函数内使用 await
async function fetchData() {
  return "Data"; // 等价于 Promise.resolve("Data")
}

     2. await 表达式

  • 暂停 async 函数执行,等待 Promise 解决
  • 只能用在 async 函数内部
async function getUser() {
  try {
    const response = await fetch("/api/user"); // 等待 Promise 解决
    const data = await response.json();        // 再次等待
    return data;
  } catch (error) {
    console.error("Fetch failed:", error);
  }
}

四、对比与转换

     Promise → async/await 转换

// Promise 版本
function loadData() {
  return fetchData()
    .then(process)
    .catch(handleError);
}

// async/await 版本
async function loadData() {
  try {
    const data = await fetchData();
    return process(data);
  } catch (error) {
    handleError(error);
  }
}

     async/await → Promise 转换

// async/await 版本
async function calculate() {
  const a = await getValueA();
  const b = await getValueB();
  return a + b;
}

// Promise 版本
function calculate() {
  return getValueA()
    .then(a => getValueB().then(b => a + b));
}

五、最佳实践与陷阱

     1. 错误处理对比

// Promise
fetchData()
  .then(handleSuccess)
  .catch(handleError); // 捕获所有上游错误

// async/await
async function main() {
  try {
    const data = await fetchData();
    handleSuccess(data);
  } catch (err) {
    handleError(err); // 需要包裹整个逻辑
  }
}

     2. 并行执行优化

// 低效(顺序执行)
const a = await fetchA();
const b = await fetchB(); // 等待 A 完成才开始

// 高效(并行执行)
const [a, b] = await Promise.all([fetchA(), fetchB()]);

     3. 循环中的注意事项

// 错误:在 forEach 中使用 await
items.forEach(async item => {
  await process(item); // 不会按预期等待
});

// 正确:使用 for...of
for (const item of items) {
  await process(item); // 顺序执行
}

六、关键区别总结

特性Promise.thenasync/await
代码结构链式调用同步风格
错误处理.catch() 方法try/catch 语句
调试体验回调跳转难跟踪直线执行易调试
返回值必须返回新 Promise自动包装为 Promise
并行处理Promise.all 显式处理需手动结合 Promise.all

七、高级模式      1. Promise 组合

// 竞速模式(第一个完成/失败的)
Promise.race([fetchA(), fetchB()]);

// 全完成(即使有失败)
Promise.allSettled([fetchA(), fetchB()]);

     2. async 函数中的 return vs return await

async function example() {
  // 直接返回:错误不会在本地捕获
  return fetchData();
  
  // 推荐:允许本地错误处理
  return await fetchData(); 
}

     3. 顶层 await(ES2022+)

// 模块顶层直接使用
const data = await fetchData();
console.log(data);

总结建议:

  1. 对于简单链式调用 → Promise.then
  2. 对于复杂异步流程 → async/await
  3. 需要并行处理时 → 结合 Promise.all 和 await
  4. 始终处理错误 → .catch() 或 try/catch

理解这些概念的关系和转换规则,能让你根据场景灵活选择最合适的异步处理方式,编写更清晰、健壮的 JavaScript 代码。

















4️⃣ 参考 4

JavaScript 异步编程全面解析:Promise、then、catch、finally、async、await

一、Promise 核心概念

     1. Promise 的本质

  • 异步操作的容器:表示一个尚未完成但预期会完成的操作
  • 三种状态
    • pending(进行中)
    • fulfilled(已成功)
    • rejected(已失败)
  • 状态不可逆:从 pending 到 fulfilled 或 rejected 后不可更改

     2. 创建 Promise

const promise = new Promise((resolve, reject) => {
  // 异步操作(API请求、定时器等)
  if (/* 成功条件 */) {
    resolve(value); // 状态变为 fulfilled
  } else {
    reject(error);  // 状态变为 rejected
  }
});

     3. Promise 生命周期

stateDiagram-v2
    [*] --> Pending
    Pending --> Fulfilled: resolve(value)
    Pending --> Rejected: reject(error)
    Fulfilled --> [*]
    Rejected --> [*]

二、Promise 链式方法

     1. .then() - 处理成功/失败

promise.then(
  onFulfilled, // (value) => { ... }
  onRejected   // 可选 (error) => { ... }
);

特性

  • 返回新 Promise,支持链式调用
  • 返回值自动包装为 Promise:
    • 返回普通值 → Promise.resolve(值)
    • 抛出错误 → Promise.reject(错误)
    • 返回 Promise → 直接传递

     2. .catch() - 错误处理

promise.catch(onRejected); // (error) => { ... }

特性

  • 捕获链中所有未处理的错误
  • 可修复错误状态(通过返回值)
  • 相当于 .then(null, onRejected)

     3. .finally() - 最终清理

promise.finally(onFinally); // () => { ... }

特性

  • 无论成功失败都会执行
  • 不接收参数(无法知道最终状态)
  • 传递原始结果(不影响返回值)
  • 适合资源清理工作

     4. 完整链式示例

fetchData()
  .then(data => process(data))     // 成功处理
  .then(result => save(result))    // 链式传递
  .catch(error => {                // 错误捕获
    console.error('失败:', error);
    return fallback();             // 错误修复
  })
  .finally(() => {                 // 最终清理
    cleanResources();
  });

三、async/await 革命性语法

     1. async 函数

async function fetchUser() {
  return { id: 1, name: 'Alice' }; 
  // 等价于 return Promise.resolve({ id: 1, name: 'Alice' })
}

特性

  • 总是返回 Promise 对象
  • 普通返回值自动包装为 resolved Promise
  • 抛出错误自动包装为 rejected Promise

     2. await 表达式

async function loadData() {
  try {
    const response = await fetch('/api/data'); // 等待Promise完成
    const data = await response.json();         // 等待JSON解析
    return process(data);
  } catch (error) {
    handleError(error);
  }
}

规则

  1. 只能在 async 函数中使用
  2. 暂停函数执行(非阻塞主线程)
  3. 返回 Promise 的解决值
  4. 如 Promise 被拒绝,抛出拒绝原因

四、Promise 与 async/await 对比

特性Promiseasync/await
代码结构链式调用同步风格
可读性回调嵌套可能复杂线性结构更清晰
错误处理.catch() 方法try/catch
调试体验断点在回调间跳转像同步代码调试
返回值显式返回Promise自动包装为Promise
循环处理需要特殊处理可使用常规循环

五、最佳实践与模式

     1. 错误处理方案

// 方案1: try/catch (推荐)
async function safeFetch() {
  try {
    const data = await fetchData();
    return process(data);
  } catch (error) {
    handleError(error);
    return fallbackValue;
  }
}

// 方案2: .catch()
fetchData()
  .then(process)
  .catch(handleError);

     2. 并行执行优化

// 顺序执行 (慢)
const user = await getUser();
const posts = await getPosts(user.id);

// 并行执行 (快)
const [user, posts] = await Promise.all([
  getUser(),
  getPosts() // 不依赖user
]);

     3. 提前启动请求

async function loadDashboard() {
  // 提前启动独立请求
  const userPromise = getUser();
  const statsPromise = getStats();
  
  // 执行其他同步任务
  renderSkeleton();
  
  // 等待需要的数据
  const [user, stats] = await Promise.all([userPromise, statsPromise]);
  renderDashboard(user, stats);
}

     4. 超时控制实现

function withTimeout(promise, timeout) {
  return Promise.race([
    promise,
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('操作超时')), timeout)
    )
  ]);
}

async function fetchWithTimeout() {
  try {
    return await withTimeout(fetch('/api'), 5000);
  } catch (error) {
    if (error.message === '操作超时') {
      return cachedData;
    }
    throw error;
  }
}

六、常见问题与解决方案

     1. Promise 常见误区

// 错误1: 忘记返回Promise
function fetchData() {
  return fetch('/api').then(res => res.json()); // 正确
}

// 错误2: 未处理拒绝
fetchData(); // ❌ 未处理可能的错误
fetchData().catch(logError); // ✅

// 错误3: 回调地狱
fetchUser(userId)
  .then(user => {
    fetchPosts(user.id).then(posts => { // ❌ 嵌套
      // ...
    });
  });

     2. async/await 陷阱

// 陷阱1: 在循环中顺序等待
async function slowProcess(items) {
  for (const item of items) {
    await process(item); // ❌ 顺序执行效率低
  }
}

// 改进方案
async function fastProcess(items) {
  await Promise.all(items.map(item => process(item))); // ✅ 并行
}

// 陷阱2: 忘记await
async function updateData() {
  const data = fetchData(); // ❌ 忘记await
  save(data); // 错误: data是Promise对象
}

七、高级应用场景

     1. 异步构造函数模式

class DataLoader {
  constructor() {
    this.initialized = this.init();
  }
  
  async init() {
    this.config = await loadConfig();
    this.cache = await createCache();
  }
  
  async getData() {
    await this.initialized; // 确保初始化完成
    return fetchData(this.config.endpoint);
  }
}

     2. 取消异步操作

function cancellable(promise) {
  let cancel;
  const wrapped = new Promise((resolve, reject) => {
    cancel = reject;
    promise.then(resolve).catch(reject);
  });
  return [wrapped, () => cancel(new Error('操作取消'))];
}

// 使用
const [fetchPromise, cancel] = cancellable(fetchData());
cancelButton.addEventListener('click', cancel);

     3. 进度通知

function withProgress(promise, onProgress) {
  return new Promise((resolve, reject) => {
    promise
      .then(result => {
        onProgress(100);
        resolve(result);
      })
      .catch(reject);
    
    // 模拟进度更新
    const interval = setInterval(() => {
      const progress = /* 计算进度 */;
      onProgress(progress);
      if (progress >= 100) clearInterval(interval);
    }, 100);
  });
}

八、执行机制与事件循环

     1. 微任务队列

console.log('开始');

Promise.resolve()
  .then(() => console.log('微任务1'))
  .then(() => console.log('微任务2'));

setTimeout(() => console.log('宏任务'), 0);

console.log('结束');

/* 输出顺序:
   开始
   结束
   微任务1
   微任务2
   宏任务
*/

     2. async/await 执行流程

sequenceDiagram
    participant M as 主线程
    participant A as async 函数
    participant P as Promise
    
    M->>A: 调用 async 函数
    A->>A: 执行同步代码
    A->>P: await 暂停执行
    M->>M: 继续执行后续代码
    P-->>A: Promise 解决
    A->>A: 恢复执行
    A->>M: 返回最终结果

九、总结与选择指南

     核心概念对比

概念角色关键特性
Promise异步操作的容器状态不可逆、支持链式调用
.then()处理异步结果返回新Promise、链式流动
.catch()错误处理捕获未处理错误、可修复状态
.finally()最终清理无视状态执行、传递原始结果
async定义异步函数自动返回Promise、启用await
await暂停异步执行等待Promise解决、同步风格编码

     何时选择何种方案

graph TD
    A[开始] --> B{简单单步操作?}
    B -->|是| C[Promise.then/catch]
    B -->|否| D{需要同步编码风格?}
    D -->|是| E[async/await]
    D -->|否| F{并行处理多个操作?}
    F -->|是| G[Promise.all + async/await]
    F -->|否| H[Promise链式调用]

     黄金法则

  1. 理解基础:掌握 Promise 状态机机制
  2. 优先 async/await:提升代码可读性和可维护性
  3. 组合使用:async/await + Promise.all 兼顾清晰与效率
  4. 始终处理错误:使用 try/catch 或 .catch() 避免未处理拒绝
  5. 合理并行化:使用 Promise.all 优化独立异步操作

通过深入理解 Promise 和 async/await 的工作原理及适用场景,您可以编写出更健壮、更高效的 JavaScript 异步代码,轻松应对从简单到复杂的各种异步编程需求。

















5️⃣ 参考 5

在 JavaScript 中,Promisethen/catch/finallyasync/await 共同构成了处理异步操作的核心机制。以下是它们的全面解析:


一、Promise 核心概念 Promise 是一个表示异步操作最终完成或失败的对象,包含三种状态:

  1. pending:初始状态(未完成)
  2. fulfilled:操作成功完成
  3. rejected:操作失败
const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (success) resolve(value); // 状态变为 fulfilled
  else reject(error);          // 状态变为 rejected
});

二、Promise 链式方法      1. .then() - 处理成功状态 接收两个回调函数(可选):

promise.then(
  value => { /* 处理成功结果 */ },
  error => { /* 可选:处理错误(不推荐) */ }
);

     2. .catch() - 捕获错误 专门处理 rejected 状态:

promise
  .then(value => { ... })
  .catch(error => { /* 捕获所有错误 */ });

     3. .finally() - 最终清理 无论成功失败都会执行:

promise
  .then(...)
  .catch(...)
  .finally(() => { /* 清理资源 */ });

三、async/await - 语法糖      1. async 函数

  • 声明异步函数,总是返回 Promise
  • 函数内可使用 await
async function fetchData() {
  return "data"; // 等价于 Promise.resolve("data")
}

     2. await 表达式

  • 暂停 async 函数执行,等待 Promise 完成
  • 只能在 async 函数中使用
async function getUser() {
  const response = await fetch('/user'); // 等待请求完成
  return response.json();
}

四、组合使用示例      完整工作流:

async function loadData() {
  try {
    // 1. 等待请求完成
    const response = await fetch('/api/data');
    
    // 2. 检查响应状态
    if (!response.ok) throw new Error('请求失败');
    
    // 3. 等待 JSON 解析
    const data = await response.json();
    
    // 4. 返回最终结果
    return { data, status: 'success' };
    
  } catch (error) {
    // 5. 错误处理
    console.error('加载失败:', error);
    return { status: 'failed' };
    
  } finally {
    // 6. 清理操作
    console.log('请求结束');
  }
}

// 使用 Promise 方法处理结果
loadData()
  .then(result => console.log(result))
  .catch(finalError => console.error(finalError)); // 最终兜底

五、关键对比与关系

特性Promise + .thenasync/await说明
代码结构链式调用类同步写法async/await 更易阅读
错误处理.catch() 或 then 的第二个参数try/catch 同步语法async/await 更直观
返回值返回新 Promise自动包装为 Promise两者本质相同
执行控制微任务队列调度函数内暂停执行底层机制一致
并行处理Promise.all()/Promise.race()需结合 Promise.all() 使用并行逻辑无差异
调试体验断点跳转可能混乱支持同步式断点调试async/await 更易调试

六、最佳实践指南

  1. 错误处理优先级

    // 👍 推荐:集中错误处理
    async function main() {
      try {
        await operation();
      } catch (error) {
        // 统一处理
      }
    }
    
    // 👎 避免:混合风格
    async function risky() {
      await operation().catch(...); // 导致部分错误被吞没
    }
    
  2. 并行优化

    // 串行(慢):
    const a = await getA();
    const b = await getB(); // 等待 getA 完成
    
    // 并行(快):
    const [a, b] = await Promise.all([getA(), getB()]);
    
  3. 循环中的注意事项

    // 错误:意外串行
    for (const url of urls) {
      await fetch(url); // 逐个请求
    }
    
    // 正确:并行请求
    const promises = urls.map(url => fetch(url));
    await Promise.all(promises);
    
  4. 避免阻塞陷阱

    // 👎 阻塞主线程
    async function blocking() {
      await heavyTask(); // 虽不阻塞主线程,但阻塞函数内后续代码
      renderUI();        // 延迟执行
    }
    
    // 👍 非阻塞优化
    function nonBlocking() {
      heavyTask().then(() => renderUI()); // 立即返回
    }
    

七、常见误区解析

  1. 忘记 await

    async function save() {
      const result = writeToDB(); // 忘记 await → 返回 Promise 而非结果
      console.log(result);        // 输出 Promise 对象
    }
    
  2. 冗余 async

    // 不必要的 async
    const getId = async () => 123; // 返回 Promise<number>
    
    // 更简洁写法
    const getId = () => Promise.resolve(123);
    
  3. 顶层 await 限制

    // 模块顶层合法(ES2022)
    const data = await fetchData(); // 需在模块环境中
    
    // 非模块环境需包裹
    (async () => {
      const data = await fetchData();
    })();
    

八、升级路线图

  1. 回调地狱Promiseasync/await
    // 回调地狱
    fs.readFile('a.txt', (err, dataA) => {
      fs.readFile('b.txt', (err, dataB) => {
        // 更多嵌套...
      });
    });
    
    // Promise 改进
    readFilePromise('a.txt')
      .then(dataA => readFilePromise('b.txt'))
      .then(dataB => ...);
    
    // async/await 终极方案
    const dataA = await readFile('a.txt');
    const dataB = await readFile('b.txt');
    

总结表格

概念角色关键特性
Promise异步操作容器状态不可逆、链式传播
.then()成功回调处理器返回新 Promise
.catch()错误捕获器捕获链中任意错误
.finally()最终清理器与状态无关,必执行
async异步函数标识符隐式返回 Promise
awaitPromise 暂停器仅限 async 函数内使用

掌握这些核心概念及其交互方式,可以编写出高效、可维护的异步 JavaScript 代码。

















6️⃣ 参考 6

JavaScript 异步编程核心:Promise 与 async/await 完全指南

     1. Promise 核心概念

  • Promise 状态
    • pending:初始状态
    • fulfilled:操作成功完成
    • rejected:操作失败
  • 创建 Promise
    const promise = new Promise((resolve, reject) => {
      if (/* 成功条件 */) {
        resolve(value); // 状态变为 fulfilled
      } else {
        reject(error); // 状态变为 rejected
      }
    });
    

     2. Promise 方法链

方法作用返回值
.then()处理成功状态新 Promise
.catch()捕获错误(推荐替代第二个参数)新 Promise
.finally()无论成功失败都会执行(ES2018)新 Promise
fetchData()
  .then(processData)      // 成功处理
  .catch(handleError)     // 错误捕获
  .finally(cleanup);      // 最终清理

     3. async/await 语法糖

  • async 函数

    async function fetchUser() {
      return { name: "John" }; // 自动包装为 Promise
    }
    
    • 总是返回 Promise
    • 普通值 → Promise.resolve(value)
    • 抛出错误 → Promise.reject(error)
  • await 操作符

    async function load() {
      const data = await fetchData(); // 暂停直到 Promise 完成
      console.log(data);
    }
    
    • 只能在 async 函数内使用
    • 暂停执行直到 Promise 完成
    • 返回 Promise 的解决值

     4. 错误处理对比

// Promise 方式
fetchData()
  .then(handleSuccess)
  .catch(handleError);

// async/await 方式
async function load() {
  try {
    const data = await fetchData();
    handleSuccess(data);
  } catch (err) {
    handleError(err);
  }
}

     5. 执行流程控制

场景Promise 方案async/await 方案
顺序执行.then()多个 await
并行执行Promise.all()await Promise.all()
首个完成Promise.race()await Promise.race()
全部完成Promise.allSettled()await Promise.allSettled()

     6. 关键特性对比

特性Promiseasync/await
代码结构链式调用同步风格
错误处理.catch() 方法try/catch
调试体验异步堆栈跟踪同步式堆栈跟踪
循环处理需用 reduce 等技巧直接使用循环语句
浏览器支持ES6+ (IE11+)ES2017+ (现代浏览器)

     7. 最佳实践示例 并行请求优化

// 高效并行
async function fetchAll() {
  const [user, posts] = await Promise.all([
    fetch('/user'),
    fetch('/posts')
  ]);
  return { user, posts };
}

循环处理

// 正确方式:并行处理数组
async function processItems(items) {
  const results = await Promise.all(
    items.map(item => processItem(item))
  );
  return results;
}

最终清理

async function transaction() {
  let conn;
  try {
    conn = await db.connect();
    const result = await conn.query('UPDATE...');
    return result;
  } catch (err) {
    await conn.rollback();
    throw err;
  } finally {
    conn?.release(); // 确保资源释放
  }
}

     8. 常见陷阱与解决方案

  1. 忘记 await

    // 错误:返回 Promise 而非结果
    async function getId() {
      return fetchId(); // 缺少 await!
    }
    
  2. 循环中的顺序等待

    // 低效:顺序执行
    for (const url of urls) {
      await fetch(url); // 依次等待
    }
    
    // 高效:并行执行
    await Promise.all(urls.map(url => fetch(url)));
    
  3. 异常穿透

    // 错误:catch 无法捕获同步错误
    async function load() {
      const data = await fetchData().catch(handleError);
      process(data); // 如果 process 抛错不会被捕获
    }
    
    // 正确:使用完整 try/catch
    async function load() {
      try {
        const data = await fetchData();
        process(data);
      } catch (err) {
        handleError(err);
      }
    }
    
  4. Promise 创建但未返回

    // 错误:嵌套 Promise 未返回
    async function save() {
      db.connect().then(conn => {
        return conn.query('INSERT...'); // 此 Promise 未传出
      });
    }
    
    // 正确:返回内部 Promise
    async function save() {
      return db.connect().then(conn => conn.query('INSERT...'));
    }
    

     9. 浏览器兼容性解决方案

<!-- 旧浏览器支持 -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.11/runtime.min.js"></script>

     10. 选择指南

场景推荐方案
简单异步操作Promise.then()
复杂异步逻辑async/await
多个独立异步操作Promise.all()
资源清理(文件/数据库)try/finally
需要取消的操作Promise + AbortController

核心原则:async/await 和 Promise 本质相通。async/await 让异步代码可读性更高,而 Promise 提供更底层的控制。现代项目中通常混合使用:async 函数内用 await 处理主要逻辑,用 .then() 处理简单副作用。

















7️⃣ 参考 7

在 JavaScript 中,Promisethen/catch/finallyasync/await 是处理异步操作的核心机制。下面我将系统性地解释这些概念,展示它们之间的关系和转换方法:

1. Promise 基础 Promise 是一个表示异步操作最终完成或失败的对象。它有三种状态:

  • Pending:初始状态
  • Fulfilled:操作成功完成
  • Rejected:操作失败
const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (/* 成功 */) {
    resolve(value); // 状态变为 fulfilled
  } else {
    reject(error);  // 状态变为 rejected
  }
});

2. then/catch/finally 方法 用于处理 Promise 的结果:

  • .then():处理成功状态(fulfilled)
  • .catch():处理失败状态(rejected)
  • .finally():无论成功失败都会执行(适合清理操作)
promise
  .then(result => {
    console.log("成功:", result);
  })
  .catch(error => {
    console.error("失败:", error);
  })
  .finally(() => {
    console.log("操作结束");
  });

3. async/await 语法糖 async/await 是基于 Promise 的语法糖,使异步代码看起来像同步代码:

  • async:声明异步函数(隐式返回 Promise)
  • await:暂停执行直到 Promise 完成(只能在 async 函数中使用)
async function fetchData() {
  try {
    const result = await promise; // 等待 Promise 完成
    console.log("成功:", result);
  } catch (error) {
    console.error("失败:", error);
  } finally {
    console.log("操作结束");
  }
}

关键概念对比表

特性Promise/thenasync/await
错误处理.catch() 方法try/catch
链式调用多级 .then()顺序同步写法
返回值返回新 Promise隐式返回 Promise
可读性回调嵌套可能复杂线性结构更清晰
并行处理Promise.all()await Promise.all()

相互转换示例

     1. Promise → async/await

// 原始 Promise 链
function getUser() {
  return fetch('/user')
    .then(response => response.json())
    .then(user => fetch(`/profile/${user.id}`))
    .catch(error => console.error(error));
}

// 转换为 async/await
async function getUser() {
  try {
    const response = await fetch('/user');
    const user = await response.json();
    return await fetch(`/profile/${user.id}`);
  } catch (error) {
    console.error(error);
  }
}

     2. async/await → Promise

// 原始 async 函数
async function processOrder() {
  const order = await fetchOrder();
  await validate(order);
  return send(order);
}

// 转换为 Promise 链
function processOrder() {
  return fetchOrder()
    .then(order => validate(order))
    .then(() => send(order));
}

错误处理对比

// Promise 风格
fetchData()
  .then(handleSuccess)
  .catch(handleError) // 捕获链中所有错误
  .finally(cleanup);

// async/await 风格
async function handleData() {
  try {
    const data = await fetchData();
    handleSuccess(data);
  } catch (err) {
    handleError(err);
  } finally {
    cleanup();
  }
}

高级用法

     并行执行

// Promise.all + then
Promise.all([fetchUser(), fetchPosts()])
  .then(([user, posts]) => render(user, posts));

// async/await 等效
async function loadAll() {
  const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
  render(user, posts);
}

     finally 的特殊性 .finally() 不接收参数,且会透传原始结果:

promise
  .finally(() => { /* 清理 */ })
  .then(result => {
    // 仍能获得原始 promise 的结果
  });

关键注意事项

  1. await 只能在 async 函数中使用

    // 错误示例
    function syncFunc() {
      const data = await fetchData(); // SyntaxError
    }
    
  2. async 函数始终返回 Promise

    async function foo() { return 42; }
    foo().then(result => console.log(result)); // 42
    
  3. 错误未捕获会导致全局错误

    // 未处理的 Promise 拒绝
    fetchData().then(); // 缺少 catch
    
  4. 避免过度顺序化

    // 低效写法(顺序等待)
    const a = await fetchA(); // 先等 A 完成
    const b = await fetchB(); // 再等 B 开始
    
    // 高效写法(并行执行)
    const [a, b] = await Promise.all([fetchA(), fetchB()]);
    
  5. await 可以接收非 Promise 值

    async function example() {
      const num = await 42; // 等同于 Promise.resolve(42)
    }
    

通过理解这些概念和转换模式,你可以根据场景灵活选择最合适的异步处理方式。现代 JavaScript 开发中通常优先使用 async/await 提升可读性,但在需要精细控制时仍会结合使用原始 Promise API。

















8️⃣ 参考 8

JavaScript 异步编程完全指南:Promise, then, catch, finally, async, await

一、核心概念全景图

graph TD
    A[异步操作] --> B[Promise]
    B --> C[then]
    B --> D[catch]
    B --> E[finally]
    B --> F[async/await]
    C --> G[链式调用]
    D --> H[错误处理]
    E --> I[清理操作]
    F --> J[同步风格]
    G --> K[顺序执行]
    J --> L[try/catch]

二、Promise 核心机制

     1. Promise 状态生命周期

const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    Math.random() > 0.5 ? 
      resolve('成功数据') : 
      reject(new Error('失败原因'));
  }, 1000);
});

// 状态变化:
// pending → fulfilled (成功)
// pending → rejected (失败)

     2. Promise 静态方法

方法描述示例
Promise.resolve()创建已解决的 PromisePromise.resolve(42)
Promise.reject()创建已拒绝的 PromisePromise.reject(error)
Promise.all()所有成功或一个失败Promise.all([p1, p2])
Promise.race()第一个解决或拒绝Promise.race([p1, p2])
Promise.allSettled()所有解决或拒绝Promise.allSettled([p1, p2])
Promise.any()第一个成功解决Promise.any([p1, p2])

三、then/catch/finally 深度解析

     1. 链式调用模式

fetch('/api/data')
  .then(response => {
    if (!response.ok) throw new Error('网络响应错误');
    return response.json();
  })
  .then(data => {
    console.log('数据:', data);
    return processData(data);
  })
  .then(processed => {
    saveData(processed);
  })
  .catch(error => {
    console.error('请求失败:', error);
    return getCachedData();
  })
  .finally(() => {
    hideLoadingSpinner();
  });

     2. 错误处理策略对比

方式特点最佳场景
then 第二个参数局部错误处理特定步骤的错误恢复
catch全局错误捕获链式调用的错误兜底
try/catch同步风格处理async/await 环境

四、async/await 革命性语法

     1. 基本用法

async function fetchUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);
    
    if (!response.ok) {
      throw new Error(`HTTP错误! 状态码: ${response.status}`);
    }
    
    const user = await response.json();
    const posts = await fetchUserPosts(user.id);
    
    return { user, posts };
  } catch (error) {
    console.error('获取用户数据失败:', error);
    return { user: null, posts: [] };
  } finally {
    console.log('用户数据请求完成');
  }
}

     2. 并行执行优化

async function loadDashboard() {
  // 并行启动所有请求
  const [userPromise, postsPromise, statsPromise] = [
    fetchUser(),
    fetchPosts(),
    fetchStats()
  ];
  
  // 顺序等待结果
  const user = await userPromise;
  const posts = await postsPromise;
  const stats = await statsPromise;
  
  // 处理数据
  return { 
    user, 
    posts: filterPosts(posts, user.preferences),
    stats: calculateMetrics(stats) 
  };
}

五、混合使用模式与转换

     1. Promise 链 → async/await 转换

// Promise 链
function processOrder() {
  return validateOrder()
    .then(order => chargePayment(order))
    .then(receipt => shipProducts(receipt))
    .catch(error => handleError(error));
}

// async/await 等效
async function processOrder() {
  try {
    const order = await validateOrder();
    const receipt = await chargePayment(order);
    return await shipProducts(receipt);
  } catch (error) {
    return handleError(error);
  }
}

     2. async/await → Promise 转换

// async/await 版本
async function getUserReports(userId) {
  const user = await getUser(userId);
  const reports = await getReports(user.department);
  return processReports(user, reports);
}

// Promise 链等效
function getUserReports(userId) {
  return getUser(userId)
    .then(user => getReports(user.department))
    .then(reports => processReports(user, reports));
}

六、高级异步模式

     1. 超时控制实现

function withTimeout(promise, timeoutMs, timeoutError = new Error('超时')) {
  return Promise.race([
    promise,
    new Promise((_, reject) => 
      setTimeout(() => reject(timeoutError), timeoutMs)
  ]);
}

// 使用
async function fetchWithTimeout() {
  try {
    const data = await withTimeout(
      fetch('/api/data'), 
      5000, 
      new Error('请求超时')
    );
    return data.json();
  } catch (error) {
    if (error.message === '请求超时') {
      return getCachedData();
    }
    throw error;
  }
}

     2. 自动重试机制

async function retry(fn, retries = 3, delay = 1000) {
  try {
    return await fn();
  } catch (error) {
    if (retries <= 0) throw error;
    await new Promise(res => setTimeout(res, delay));
    return retry(fn, retries - 1, delay * 2); // 指数退避
  }
}

// 使用
async function fetchData() {
  return retry(() => fetch('/api/unstable'), 5);
}

     3. 并发控制

async function runParallel(tasks, concurrency = 5) {
  const results = [];
  const executing = [];
  
  for (const task of tasks) {
    const p = task().then(result => {
      executing.splice(executing.indexOf(p), 1);
      return result;
    });
    
    results.push(p);
    executing.push(p);
    
    if (executing.length >= concurrency) {
      await Promise.race(executing);
    }
  }
  
  return Promise.all(results);
}

// 使用
async function processImages(images) {
  const tasks = images.map(img => () => processImage(img));
  return runParallel(tasks, 3); // 最大并发3
}

七、错误处理最佳实践

     1. 分层错误处理

async function mainWorkflow() {
  try {
    // 核心业务逻辑
    const input = await loadInput();
    const processed = await processData(input);
    await saveResults(processed);
  } catch (error) {
    // 业务逻辑错误处理
    if (error instanceof ValidationError) {
      await logValidationError(error);
      return { status: 'invalid' };
    }
    
    if (error instanceof NetworkError) {
      await retryOperation();
      return { status: 'retrying' };
    }
    
    // 无法处理的错误重新抛出
    throw error; 
  }
}

// 顶层调用
mainWorkflow()
  .then(result => console.log('完成:', result))
  .catch(error => {
    // 全局兜底错误处理
    console.error('未处理的错误:', error);
    sendErrorToMonitoring(error);
    process.exit(1);
  });

     2. 错误类型化

class AppError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
    this.name = this.constructor.name;
  }
}

class ApiError extends AppError {
  constructor(endpoint, status) {
    super(`${endpoint} 请求失败`, 'API_ERROR');
    this.status = status;
  }
}

// 使用
async function fetchResource() {
  try {
    const res = await fetch('/api/resource');
    if (!res.ok) throw new ApiError('/api/resource', res.status);
    return res.json();
  } catch (error) {
    if (error instanceof ApiError && error.status === 404) {
      return getFallbackData();
    }
    throw error;
  }
}

八、性能优化策略

     1. 避免阻塞事件循环

// 错误:阻塞主线程
async function processLargeArray(array) {
  const results = [];
  for (const item of array) {
    // 同步CPU密集型操作
    const result = cpuIntensiveTask(item);
    results.push(result);
  }
  return results;
}

// 正确:使用任务分割
async function processLargeArray(array) {
  const CHUNK_SIZE = 1000;
  const results = [];
  
  for (let i = 0; i < array.length; i += CHUNK_SIZE) {
    const chunk = array.slice(i, i + CHUNK_SIZE);
    
    // 使用setTimeout释放事件循环
    await new Promise(resolve => setTimeout(resolve, 0));
    
    results.push(...processChunk(chunk));
  }
  
  return results;
}

     2. 内存管理

async function processStream() {
  const stream = getDataStream();
  let buffer = [];
  
  for await (const chunk of stream) {
    buffer.push(chunk);
    
    if (buffer.length >= 1000) {
      await processBatch(buffer);
      buffer = []; // 清除引用,防止内存泄漏
    }
  }
  
  if (buffer.length > 0) {
    await processBatch(buffer);
  }
}

九、现代异步编程全景图

     1. 进化历程

回调函数 → PromiseGeneratorasync/await → 顶层await

     2. 技术选型指南

场景推荐方案示例
简单异步Promise.thenfetch(url).then(r => r.json())
复杂流程async/await包含条件/循环的异步逻辑
并行操作Promise.all同时发起多个独立请求
错误恢复catch + 条件判断特定错误类型恢复
资源清理finally关闭文件/数据库连接
浏览器环境async/await + try/catch前端应用逻辑
Node.js 流for-await-of处理大文件流

     3. 终极实践模板

async function robustAsyncOperation(params) {
  try {
    // 1. 准备阶段
    const config = await loadConfig();
    
    // 2. 并行获取数据
    const [primaryData, secondaryData] = await Promise.all([
      fetchPrimaryData(config),
      fetchSecondaryData(config)
    ]);
    
    // 3. 处理数据
    const processed = processData(primaryData, secondaryData);
    
    // 4. 保存结果
    await saveResult(processed);
    
    // 5. 返回成功
    return { status: 'success', data: processed };
  } catch (error) {
    // 错误分类处理
    if (error instanceof NetworkError) {
      console.warn('网络错误,使用缓存数据');
      return { status: 'cached', data: getCachedData() };
    }
    
    if (error instanceof ValidationError) {
      console.error('数据验证失败:', error.details);
      throw new CriticalError('INVALID_DATA', error);
    }
    
    // 未知错误
    console.error('未知错误:', error);
    throw error;
  } finally {
    // 资源清理
    releaseResources();
    trackOperationEnd();
  }
}

十、未来趋势

     1. 顶层 await (ES2022)

// 模块顶层直接使用 await
const data = await fetchConfig();
export default processData(data);

     2. Promise.withResolvers (ES2024)

const { promise, resolve, reject } = Promise.withResolvers();

setTimeout(() => {
  resolve('成功结果');
}, 1000);

await promise;

     3. 异步上下文

// 实验性特性
const asyncContext = new AsyncContext();

async function main() {
  asyncContext.set('requestId', generateId());
  
  await fetchData(); // 所有异步操作共享上下文
  await processData();
  
  console.log('请求ID:', asyncContext.get('requestId'));
}

总结

JavaScript 异步编程的核心要点:

  1. Promise 是基础:所有现代异步操作的基石
  2. then/catch/finally 链式调用:提供顺序执行、错误处理和清理机制
  3. async/await 革命:用同步方式写异步代码,提升可读性
  4. 错误处理是关键:分层处理、类型化错误和全局兜底
  5. 性能优化不可忽视:并行执行、流处理和内存管理
  6. 混合使用更强大:根据场景选择最佳组合模式
graph LR
    A[异步操作] --> B[Promise]
    B --> C[.then]
    B --> D[.catch]
    B --> E[.finally]
    B --> F[async]
    F --> G[await]
    C --> H[链式调用]
    D --> I[错误处理]
    E --> J[清理操作]
    G --> K[同步风格]
    H --> L[顺序执行]
    K --> M[try/catch]
    I --> N[错误恢复]
    J --> O[资源释放]

掌握这些异步编程技术,能让你构建更健壮、高效和可维护的 JavaScript 应用程序。无论是浏览器端还是 Node.js 环境,这些核心概念都是现代 JavaScript 开发者的必备技能。

















9️⃣ 参考 9

在 JavaScript 中,Promiseasync/await 是处理异步操作的两种核心机制。下面我将系统化地解释这些概念及其相互关系:


1. Promise 基础 Promise 对象表示异步操作的最终完成(或失败)及其结果值。

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求)
  setTimeout(() => {
    Math.random() > 0.5 
      ? resolve("成功数据") 
      : reject("错误原因")
  }, 1000);
});

2. Promise 方法链      .then() - 处理成功状态

promise.then(result => {
  console.log("成功:", result);
});

     .catch() - 处理失败状态

promise.catch(error => {
  console.error("失败:", error);
});

     .finally() - 无论成功失败都执行

promise.finally(() => {
  console.log("操作结束");
});

     链式调用示例

fetch("/api/data")
  .then(response => response.json())
  .then(data => processData(data))
  .catch(error => handleError(error))
  .finally(() => cleanUp());

3. async/await 语法糖 基于 Promise 的语法扩展,使异步代码看起来像同步代码。

     async 函数声明

async function fetchData() {
  // 函数始终返回 Promise
}

     await 操作符

async function getUser() {
  try {
    const response = await fetch("/api/user"); // 暂停执行直到 Promise 解决
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
  }
}

4. 关键差异对比

特性Promise 链async/await
可读性回调嵌套可能复杂顺序执行,类似同步代码
错误处理.catch() 方法try/catch
调试难追踪链式调用支持同步式断点调试
返回值必须返回新 Promise自动包装为 Promise
循环处理需用 Promise.all 等组合可直接用 for 循环

5. 相互转换规则      Promise → async/await

// 原始
function loadData() {
  return fetchData()
    .then(process)
    .catch(handleError);
}

// 转换后
async function loadData() {
  try {
    const data = await fetchData();
    return process(data);
  } catch (err) {
    handleError(err);
  }
}

     async/await → Promise

// 原始
async function calculate() {
  const a = await getA();
  const b = await getB();
  return a + b;
}

// 转换后
function calculate() {
  return getA()
    .then(a => getB().then(b => a + b));
}

6. 高级模式      并行执行优化

// 顺序执行 (慢)
async function sequential() {
  const a = await task(1000);
  const b = await task(2000); // 等待前一个完成
}

// 并行执行 (快)
async function parallel() {
  const [a, b] = await Promise.all([
    task(1000), 
    task(2000) // 同时启动
  ]);
}

     错误处理模式对比

// Promise 链错误穿透
fetchData()
  .then()
  .then()
  .catch() // 捕获前面所有错误

// async/await 局部捕获
async function process() {
  try {
    const a = await step1();
  } catch (err) {
    handleStep1Error(err); // 仅捕获 step1 错误
  }
  
  const b = await step2(); // 继续执行
}

7. 关键注意事项

  1. 避免 await 滥用

    // 反模式 - 不必要的串行
    const a = await getA(); // 等待 1s
    const b = await getB(); // 再等待 1s (总 2s)
    
    // 正确并行
    const [a, b] = await Promise.all([getA(), getB()]); // 总 1s
    
  2. 返回 await 的特殊情况

    async function foo() {
      return await bar(); 
      // 与 return bar() 的区别:
      // 1. 会等待 bar() 的微任务
      // 2. 能在 try/catch 中捕获错误
    }
    
  3. Promise 构造函数反模式

    // 错误:将 async 函数包装在 new Promise 中
    const promise = new Promise(async (resolve, reject) => {
      try {
        const data = await fetchData(); // 可能导致未处理错误
        resolve(data);
      } catch (err) {
        reject(err);
      }
    });
    
    // 正确:直接使用 async 函数
    const promise = fetchData(); // 自动返回 Promise
    

总结

概念用途
Promise异步操作的容器,提供标准化管理接口
.then()处理 Promise 成功状态
.catch()处理 Promise 失败状态
.finally()无论成功失败都执行的清理逻辑
async声明异步函数,使其隐式返回 Promise
await暂停 async 函数执行,等待 Promise 解决

选择原则

  • 简单链式调用 → Promise 链
  • 复杂异步逻辑 → async/await
  • 并行任务 → Promise.all/Promise.race 配合 await

















🔟 参考 10

JavaScript 异步编程:Promise 与 async/await 深度解析

JavaScript 的异步编程经历了从回调地狱到 Promise,再到 async/await 的演变。下面我将全面解析这些核心概念及其关系。

核心概念一览

概念描述使用场景
Promise表示异步操作的最终结果所有异步操作的基础
then()处理 Promise 成功状态链式调用异步操作
catch()处理 Promise 失败状态错误处理
finally()无论成功失败都会执行清理操作
async声明异步函数创建支持 await 的函数
await等待 Promise 解决在 async 函数中暂停执行

1. Promise:异步操作的容器

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

  • pending:初始状态
  • fulfilled:操作成功完成
  • rejected:操作失败
// 创建 Promise
const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    const success = Math.random() > 0.5;
    success ? resolve("操作成功!") : reject("操作失败!");
  }, 1000);
});

2. then():处理成功状态

then() 方法用于处理 Promise 的解决值:

promise.then(
  result => {
    console.log("成功:", result);
    return result.toUpperCase(); // 返回值将包装为新 Promise
  },
  error => {
    console.error("失败:", error);
    throw new Error("处理错误"); // 抛出错误将进入 catch
  }
);

3. catch():处理错误状态

专门处理 Promise 链中的错误:

promise
  .then(result => {
    console.log(result);
    throw new Error("处理中出错"); // 模拟错误
  })
  .catch(error => {
    console.error("捕获错误:", error.message);
    return "错误已处理"; // 恢复执行
  });

4. finally():清理操作

无论成功失败都会执行,适合清理资源:

let isLoading = true;

fetch("https://api.example.com/data")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("请求失败", error))
  .finally(() => {
    isLoading = false;
    console.log("请求结束");
  });

5. async:声明异步函数

async 函数总是返回 Promise:

async function fetchUser(userId) {
  if (!userId) throw new Error("缺少用户ID");
  
  return { id: userId, name: "张三" };
}

// 等效于:
function fetchUser(userId) {
  return new Promise((resolve, reject) => {
    if (!userId) reject(new Error("缺少用户ID"));
    resolve({ id: userId, name: "张三" });
  });
}

6. await:暂停执行等待 Promise

只能在 async 函数内部使用:

async function getUserDetails(userId) {
  try {
    console.log("开始获取用户数据...");
    const user = await fetchUser(userId); // 暂停直到 Promise 解决
    
    console.log("开始获取用户订单...");
    const orders = await fetchOrders(user.id);
    
    return { ...user, orders };
  } catch (error) {
    console.error("获取用户详情失败:", error);
    return null;
  } finally {
    console.log("用户详情获取流程结束");
  }
}

Promise 与 async/await 转换

     Promise.then → async/await

// Promise 链
function loadData() {
  return fetchData()
    .then(processData)
    .then(saveData)
    .catch(handleError);
}

// async/await 等效
async function loadData() {
  try {
    const rawData = await fetchData();
    const processed = await processData(rawData);
    return await saveData(processed);
  } catch (error) {
    handleError(error);
  }
}

     async/await → Promise.then

// async/await
async function calculate() {
  const a = await getValueA();
  const b = await getValueB();
  return a + b;
}

// Promise 链等效
function calculate() {
  return getValueA()
    .then(a => getValueB().then(b => a + b));
}

高级模式与最佳实践

     1. 并行执行

// 顺序执行 - 慢
async function sequential() {
  const user = await fetchUser();
  const posts = await fetchPosts(user.id);
  return { user, posts };
}

// 并行执行 - 快
async function parallel() {
  const [user, posts] = await Promise.all([
    fetchUser(), 
    fetchPosts()
  ]);
  
  return { user, posts };
}

     2. 错误处理策略

// 方式1:try/catch(推荐)
async function safeFetch() {
  try {
    const response = await fetch(url);
    return response.json();
  } catch (error) {
    console.error("请求失败:", error);
    return null;
  }
}

// 方式2:catch() 方法
async function safeFetch() {
  const response = await fetch(url).catch(error => {
    console.error("请求失败:", error);
    return null;
  });
  
  return response?.json();
}

// 方式3:混合模式
async function main() {
  const data = await fetchData().catch(handleError);
  
  if (!data) return;
  
  // 处理数据...
}

     3. Promise 工具方法

// 任意一个成功
const firstSuccess = await Promise.any([
  fetchFromSourceA(), 
  fetchFromSourceB()
]);

// 等待所有完成(无论成功失败)
const allResults = await Promise.allSettled([
  updateProfile(),
  savePreferences()
]);

     4. 避免常见陷阱

// 错误:在循环中顺序等待
async function slowProcess(items) {
  for (const item of items) {
    await processItem(item); // 每次循环等待完成
  }
}

// 正确:并行处理
async function fastProcess(items) {
  await Promise.all(items.map(processItem));
}

// 错误:忘记 await
async function getData() {
  const promise = fetchData(); // 缺少 await
  console.log(promise); // 输出 Promise 对象而非结果
}

浏览器兼容性与现代用法

所有现代浏览器(Chrome、Firefox、Safari、Edge)和 Node.js(v7.6+)都原生支持这些特性。对于旧环境,可通过 Babel 转译。

     顶级 await(ES2022)

现代环境支持在模块顶层使用 await:

// 模块中直接使用
const data = await fetchData();
console.log(data);

总结对比

特性Promise.thenasync/await
代码结构链式调用线性同步风格
可读性中等
错误处理.catch()try/catch
调试体验一般优秀
流程控制需要手动组合更直观

最佳实践建议

  1. 新项目优先使用 async/await
  2. 简单操作可使用 Promise.then
  3. 并行任务使用 Promise.all/Promise.any
  4. 始终处理可能的错误
  5. 使用 finally 进行资源清理
graph TD
    A[异步操作] --> B{Promise}
    B -->|成功| C[then]
    B -->|失败| D[catch]
    C & D --> E[finally]
    F[async函数] --> G[await Promise]
    G --> H[处理结果]
    G --> I[捕获错误]
    H & I --> J[返回新Promise]

掌握这些核心概念,你将能够编写更清晰、更健壮的异步 JavaScript 代码!

















🤔 参考 11

JavaScript 异步编程终极指南:Promise 与 async/await

一、Promise 核心体系

     1. Promise 基础

  • 本质:表示异步操作的容器
  • 状态
    • pending(等待中)
    • fulfilled(已成功)
    • rejected(已失败)
  • 不可逆:状态一旦改变不可回退
// 创建 Promise
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random() > 0.5 
      ? resolve("成功!") 
      : reject(new Error("失败!"));
  }, 1000);
});

     2. Promise 链式方法

         .then(onFulfilled, onRejected)

  • 处理成功状态(核心方法)
  • 返回新 Promise 支持链式调用
  • 值穿透:未提供回调时直接传递值
fetchData()
  .then(data => {
    console.log("第一步:", data);
    return process(data); // 返回新值/Promise
  })
  .then(processed => {
    console.log("第二步:", processed);
  });

         .catch(onRejected)

  • 专门处理拒绝状态
  • 本质是 .then(null, onRejected) 的语法糖
  • 捕获链中所有未处理的错误
apiCall()
  .then(handleSuccess)
  .catch(error => {
    console.error("全局捕获:", error);
    return fallbackValue; // 提供恢复值
  });

         .finally(onFinally)

  • 无论成功失败都会执行
  • 不接收参数,不影响最终值
  • 最适合执行清理操作
let loading = true;

fetchResource()
  .then(data => save(data))
  .catch(logError)
  .finally(() => {
    loading = false; // 清理状态
    console.log("请求结束");
  });

     3. 静态方法

方法描述示例
Promise.resolve()创建已解决的 PromisePromise.resolve(42)
Promise.reject()创建已拒绝的 PromisePromise.reject(error)
Promise.all()所有成功时返回结果数组Promise.all([p1, p2])
Promise.race()返回最先完成的 PromisePromise.race([req, timeout])
Promise.allSettled()所有完成后返回状态数组Promise.allSettled([p1, p2])
Promise.any()任一成功即返回结果Promise.any([p1, p2])

二、async/await 革命

     1. async 函数

  • 声明:函数前添加 async 关键字
  • 返回值:总是返回 Promise 对象
    • 返回非 Promise → 包装为 resolved Promise
    • 抛出错误 → 返回 rejected Promise
async function getUser() {
  return { id: 1, name: "John" }; // 自动包装为Promise
}

// 等价于
function getUser() {
  return Promise.resolve({ id: 1, name: "John" });
}

     2. await 表达式

  • 作用:暂停 async 函数执行,等待 Promise 解决
  • 规则
    • 只能在 async 函数内部使用
    • 返回 Promise 的解决值
    • 遇到 rejection 抛出异常
async function fetchData() {
  try {
    const response = await fetch('/api/data'); // 暂停等待
    const data = await response.json(); // 再次等待
    return data;
  } catch (error) {
    console.error("请求失败:", error);
  }
}

三、混合应用模式

     1. 错误处理策略

// 混合错误处理
async function robustFetch() {
  try {
    const response = await fetch('/data').catch(handleNetworkError);
    
    if (!response.ok) {
      throw new Error('API响应错误');
    }
    
    return response.json();
  } catch (error) {
    if (error instanceof TypeError) {
      return cachedData();
    }
    throw error;
  }
}

     2. 并行优化技巧

async function loadDashboard() {
  // 并行启动请求
  const userPromise = fetchUser();
  const ordersPromise = fetchOrders();
  
  // 顺序处理依赖数据
  const user = await userPromise;
  const recommendations = await getRecommendations(user.id);
  
  // 等待并行结果
  const [orders] = await Promise.all([ordersPromise]);
  
  return { user, orders, recommendations };
}

     3. 循环控制模式

// 顺序执行
async function processQueue(tasks) {
  for (const task of tasks) {
    await task.execute(); // 顺序执行
  }
}

// 并行执行(控制并发数)
async function parallelProcess(tasks, concurrency = 5) {
  const results = [];
  
  for (let i = 0; i < tasks.length; i += concurrency) {
    const batch = tasks.slice(i, i + concurrency);
    const batchResults = await Promise.all(
      batch.map(task => task.execute())
    );
    results.push(...batchResults);
  }
  
  return results;
}

四、最佳实践指南

     1. 错误处理黄金法则

// 推荐:async/await + try/catch
async function safeOperation() {
  try {
    const result = await riskyOperation();
    return process(result);
  } catch (error) {
    if (error instanceof SpecificError) {
      return handleSpecificError(error);
    }
    logger.error(error);
    throw new AppError('操作失败', { cause: error });
  } finally {
    cleanupResources();
  }
}

// Promise等效实现
function safeOperationPromise() {
  return riskyOperation()
    .then(process)
    .catch(error => {
      if (error instanceof SpecificError) {
        return handleSpecificError(error);
      }
      logger.error(error);
      return Promise.reject(new AppError('操作失败', { cause: error }));
    })
    .finally(cleanupResources);
}

     2. 性能优化策略

模式反例正例
并行请求const a = await getA(); const b = await getB();const [a, b] = await Promise.all([getA(), getB()])
提前启动await a; await b;const a = getA(); const b = getB(); await a; await b;
缓存请求每次重新请求使用内存/缓存存储Promise

     3. 常见陷阱及解决方案

  1. 忘记await

    // 错误
    async function saveData() {
      const data = fetchData(); // 返回Promise而不是数据
      store.save(data); // 保存的是Promise对象
    }
    
    // 正确
    async function saveData() {
      const data = await fetchData();
      store.save(data);
    }
    
  2. 异常吞噬

    // 危险:未处理的拒绝
    async function dangerous() {
      const promise = fetchData(); // 缺少await
      // 如果fetchData拒绝,会产生未处理的拒绝
    }
    
    // 安全方案
    async function safe() {
      const promise = fetchData().catch(logError); // 添加错误处理
      // 或
      try {
        const data = await fetchData();
      } catch (error) {/*...*/}
    }
    
  3. 循环中的并发失控

    // 危险:可能创建数万个并发请求
    async function massRequests() {
      const urls = [/* 大量URL */];
      const results = await Promise.all(urls.map(fetch));
    }
    
    // 安全:限制并发数
    import pLimit from 'p-limit';
    
    async function controlledRequests() {
      const limit = pLimit(10); // 最大并发数
      const urls = [/* 大量URL */];
      
      const promises = urls.map(url => 
        limit(() => fetch(url))
      );
      
      return Promise.all(promises);
    }
    

五、高级应用场景

     1. 取消机制实现

function cancellablePromise(executor) {
  let rejectFn;
  
  const promise = new Promise((resolve, reject) => {
    rejectFn = reject;
    executor(resolve, reject);
  });
  
  return {
    promise,
    cancel: (reason = "已取消") => rejectFn(new CancellationError(reason))
  };
}

// 使用示例
const { promise, cancel } = cancellablePromise(resolve => {
  setTimeout(() => resolve("完成"), 5000);
});

// 用户取消操作
cancelButton.addEventListener('click', () => cancel("用户取消"));

     2. 进度跟踪

function trackablePromise(executor) {
  const progressHandlers = [];
  
  const promise = new Promise((resolve, reject) => {
    executor(
      resolve, 
      reject,
      progress => {
        progressHandlers.forEach(handler => handler(progress));
      }
    );
  });
  
  return {
    promise,
    onProgress: handler => {
      progressHandlers.push(handler);
      return this;
    }
  };
}

// 使用示例
const fileUpload = trackablePromise((resolve, reject, progress) => {
  // 模拟上传进度
  let percent = 0;
  const interval = setInterval(() => {
    percent += 10;
    progress(percent);
    if (percent >= 100) {
      clearInterval(interval);
      resolve();
    }
  }, 500);
});

fileUpload.onProgress(p => console.log(`${p}%`))
  .promise
  .then(() => console.log("上传完成"));

六、浏览器支持与兼容方案

     1. 支持情况

特性浏览器支持Node.js 支持
PromiseChrome 32+, FF 29+, ES6+Node 0.12+
async/awaitChrome 55+, FF 52+, ES8+Node 7.6+
finallyChrome 63+, FF 58+, ES10Node 10+
allSettledChrome 76+, FF 71+, ES11Node 12.9+

     2. 兼容方案

<!-- 旧浏览器支持 -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.11/runtime.min.js"></script>

<!-- Babel 转译 async/await -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// async/await 代码
</script>

七、总结:选择指南

  1. 简单异步操作:直接使用 Promise

    fetchData()
      .then(process)
      .catch(handleError);
    
  2. 复杂异步流程:首选 async/await

    async function complexFlow() {
      try {
        const a = await step1();
        const b = await step2(a);
        return await step3(b);
      } catch (error) {
        handleError(error);
      }
    }
    
  3. 并行处理:Promise.all + async/await

    async function parallelTasks() {
      const [res1, res2] = await Promise.all([task1(), task2()]);
      // 处理结果
    }
    
  4. 终极建议

    graph TD
      A[开始异步操作] --> B{简单单步?}
      B -->|是| C[使用Promise.then]
      B -->|否| D{需要并行?}
      D -->|是| E[Promise.all + async/await]
      D -->|否| F[纯async/await]
      C --> G[结束]
      E --> G
      F --> G
    

掌握 Promise 和 async/await 的组合使用,能够让你编写出既高效又易维护的异步 JavaScript 代码,彻底告别回调地狱,构建现代化的 Web 应用。

















🤔 参考 12

在 JavaScript 中,Promise、then/catch/finally 和 async/await 是处理异步操作的核心机制。以下是它们的详细解释和相互关系:


1. Promise(承诺) Promise 对象表示一个异步操作的最终完成(或失败)及其结果值。

const promise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  if (/* 成功 */) resolve("Success!"); // 状态变为 fulfilled
  else reject("Error!");              // 状态变为 rejected
});

三种状态

  • pending:初始状态
  • fulfilled:操作成功完成
  • rejected:操作失败

2. .then() / .catch() / .finally() Promise 的链式调用方法:      .then() - 处理成功状态

promise.then(
  result => console.log(result), // 成功时执行
  error => console.error(error)   // 失败时执行(可选)
);

     .catch() - 专门处理错误

promise
  .then(result => console.log(result))
  .catch(error => console.error("Caught:", error)); // 捕获所有错误

     .finally() - 无论成功失败都会执行

promise
  .then(/* ... */)
  .catch(/* ... */)
  .finally(() => console.log("Cleanup")); // 如关闭加载动画

3. async / await(语法糖) 基于 Promise 的语法糖,使异步代码看起来像同步代码。

     async 函数

  • 总是返回一个 Promise
  • 允许在函数内使用 await
async function fetchData() {
  return "Data"; // 自动包装为 Promise.resolve("Data")
}

     await 表达式

  • 暂停 async 函数的执行,等待 Promise 解决
  • 只能在 async 函数中使用
async function getUser() {
  try {
    const response = await fetch("/api/user"); // 等待 Promise 解决
    const data = await response.json();        // 再次等待
    return data;
  } catch (error) {
    console.error("Failed:", error);
  }
}

4. 核心关系

graph LR
  A[Promise] --> B[.then/.catch/.finally]
  A --> C[async/await]
  B -->|底层机制| C
  C -->|语法糖| B
  • Promise 是基础:所有异步操作的核心
  • .then/.catch/.finally:直接操作 Promise 的方法
  • async/await:基于 Promise 的语法糖,更易读写

5. 关键对比

特性Promise 链async/await
可读性回调嵌套较复杂类似同步代码,更清晰
错误处理.catch() 链式捕获try/catch 块捕获
调试回调中断点难追踪支持同步式断点调试
返回值返回新 Promise隐式返回 Promise
并行处理Promise.all()await Promise.all()

6. 最佳实践示例      组合使用

// 并行请求 + 错误处理
async function fetchAll() {
  try {
    const [users, posts] = await Promise.all([
      fetch("/users"),
      fetch("/posts")
    ]);
    return { users, posts };
  } catch (error) {
    console.error("Parallel fetch failed:", error);
    throw error; // 重新抛出错误
  } finally {
    console.log("Request completed");
  }
}

// 调用
fetchAll()
  .then(data => console.log(data))
  .catch(err => console.error("Global catch:", err));

     避免常见陷阱

// ❌ 错误:顺序等待(应并行)
async function slowFetch() {
  const a = await fetchA(); // 等待完成
  const b = await fetchB(); // 再开始(效率低)
}

// ✅ 正确:并行请求
async function fastFetch() {
  const [a, b] = await Promise.all([fetchA(), fetchB()]);
}

// ❌ 错误:忘记 await
async function oops() {
  const data = fetchData(); // 返回 Promise 而非实际数据
  console.log(data);        // 输出 Promise 对象
}

7. 执行顺序图解

console.log("Start");

setTimeout(() => console.log("Timeout"), 0);

Promise.resolve("Promise")
  .then(res => console.log(res));

async function test() {
  console.log("Async start");
  await Promise.resolve();
  console.log("Async end");
}

test();

console.log("End");

/* 输出顺序:
Start
Async start
End
Promise     // 微任务优先于宏任务
Async end
Timeout
*/

执行规则

  1. 同步代码 > 微任务(Promise.then) > 宏任务(setTimeout)
  2. await 后的代码相当于 .then() 回调(微任务)

总结

  • Promise:异步操作的容器
  • .then/.catch/.finally:直接操作 Promise 的方法
  • async/await:基于 Promise 的语法糖,简化异步流程控制
  • 优先使用 async/await:提高代码可读性
  • 保留 Promise 知识:用于底层优化和特殊场景(如 Promise.race()

















🤔 参考 13

JavaScript 异步编程全面解析:Promise 与 async/await

下面我将详细讲解 JavaScript 中的 Promise、then、catch、finally、async 和 await 这些核心异步编程概念,并提供实用示例。

1. Promise(承诺)

Promise 是 JavaScript 中处理异步操作的核心对象,代表一个异步操作的最终完成(或失败)及其结果值。

     基本结构:

const myPromise = new Promise((resolve, reject) => {
  // 异步操作(如 API 请求、定时器等)
  
  if (/* 操作成功 */) {
    resolve('成功数据'); // 将 Promise 状态改为 fulfilled
  } else {
    reject('错误原因'); // 将 Promise 状态改为 rejected
  }
});

     Promise 的三种状态:

  1. pending:初始状态
  2. fulfilled:操作成功完成
  3. rejected:操作失败

2. .then() 方法

.then() 用于处理 Promise 的完成状态(fulfilled):

myPromise.then(
  (result) => {
    console.log('成功:', result);
  },
  (error) => {
    console.error('失败:', error);
  }
);

     链式调用:

fetchData()
  .then(processData)
  .then(saveData)
  .then(finalize);

3. .catch() 方法

.catch() 专门用于捕获 Promise 链中的错误:

fetchData()
  .then(processData)
  .then(saveData)
  .catch(error => {
    console.error('处理过程中出错:', error);
    return fallbackData(); // 提供回退方案
  });

4. .finally() 方法

.finally() 无论 Promise 成功还是失败都会执行,适合清理操作:

let isLoading = true;

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => {
    isLoading = false; // 无论成功失败都会执行
    console.log('请求结束');
  });

5. async/await

async/await 是基于 Promise 的语法糖,使异步代码看起来像同步代码。

     async 函数:

async function fetchUserData() {
  // 函数始终返回 Promise
  return { name: 'John', age: 30 };
}

// 等同于:
function fetchUserData() {
  return Promise.resolve({ name: 'John', age: 30 });
}

     await 表达式:

async function getUser() {
  try {
    const response = await fetch('/api/user'); // 暂停执行直到 Promise 完成
    const data = await response.json(); // 再次等待
    console.log(data);
    return data;
  } catch (error) {
    console.error('获取用户失败:', error);
  }
}

6. 综合使用示例

     用户认证流程:

async function authenticateUser(username, password) {
  try {
    // 1. 验证输入
    if (!username || !password) {
      throw new Error('用户名和密码不能为空');
    }
    
    // 2. 获取用户数据
    const user = await fetchUser(username);
    
    // 3. 验证密码
    const isValid = await validatePassword(user, password);
    
    if (!isValid) {
      throw new Error('密码错误');
    }
    
    // 4. 生成访问令牌
    const token = await generateToken(user);
    
    return { success: true, token };
    
  } catch (error) {
    console.error('认证失败:', error.message);
    return { success: false, error: error.message };
    
  } finally {
    // 5. 清理资源(无论成功失败都执行)
    cleanUpResources();
  }
}

// 使用示例
authenticateUser('john_doe', 'secure123')
  .then(result => {
    if (result.success) {
      console.log('认证成功,令牌:', result.token);
    } else {
      console.log('认证失败:', result.error);
    }
  });

7. 最佳实践与常见模式

     并行操作优化:

async function loadDashboard() {
  // 同时发起三个并行请求
  const [user, orders, notifications] = await Promise.all([
    fetchUser(),
    fetchOrders(),
    fetchNotifications()
  ]);
  
  return { user, orders, notifications };
}

     错误处理模式:

// 方法1:try/catch
async function fetchData() {
  try {
    const data = await apiCall();
    return data;
  } catch (error) {
    // 处理错误
  }
}

// 方法2:catch() 方法
async function fetchData() {
  const data = await apiCall().catch(error => {
    // 处理错误
    return fallbackData;
  });
  return data;
}

     循环中的异步操作:

// 顺序执行
async function processArray(array) {
  for (const item of array) {
    await processItem(item); // 逐个处理
  }
}

// 并行执行
async function processArray(array) {
  const promises = array.map(item => processItem(item));
  await Promise.all(promises); // 同时处理所有项
}

8. Promise 与 async/await 对比

特性Promise.then()async/await
语法链式调用同步风格
错误处理.catch() 方法try/catch 块
可读性回调嵌套可能降低可读性类似同步代码,更易理解
调试调试困难类似同步代码,易于调试
返回值返回新的 Promise自动包装为 Promise
流程控制需要手动返回 Promise使用 await 暂停执行

9. 常见错误与解决方案

  1. 忘记 await

    // ❌ 错误:返回Promise而不是结果
    async function getData() {
      const data = fetch('/api'); // 缺少await
      return data;
    }
    
    // ✅ 正确
    async function getData() {
      const data = await fetch('/api');
      return data;
    }
    
  2. 忽略错误处理

    // ❌ 危险:未处理可能的错误
    async function updateProfile() {
      await saveData();
    }
    
    // ✅ 安全
    async function updateProfile() {
      try {
        await saveData();
      } catch (error) {
        handleError(error);
      }
    }
    
  3. 不必要的顺序等待

    // ❌ 低效:顺序等待
    async function loadResources() {
      const a = await getA(); // 等待A完成
      const b = await getB(); // 再等待B完成
    }
    
    // ✅ 高效:并行请求
    async function loadResources() {
      const [a, b] = await Promise.all([getA(), getB()]);
    }
    

总结

JavaScript 的异步编程从回调函数发展到 Promise,再到现在的 async/await,提供了越来越强大的工具来处理异步操作:

  1. Promise:异步操作的容器
  2. .then():处理成功状态
  3. .catch():捕获错误
  4. .finally():执行清理操作
  5. async:声明异步函数
  6. await:暂停执行直到 Promise 完成

最佳实践

  • 优先使用 async/await 编写更清晰的异步代码
  • 始终处理可能的错误(使用 try/catch 或 .catch())
  • 并行操作使用 Promise.all() 提高性能
  • 使用 .finally() 进行必要的资源清理
  • 避免在循环中滥用顺序等待

掌握这些核心概念和模式,你将能够编写出高效、健壮且易于维护的 JavaScript 异步代码。