一、Promise 核心概念

  1. Promise 是什么?
    Promise 是 JavaScript 中用于处理异步操作的对象,它代表一个尚未完成但预期将来会完成的操作

  2. Promise 的三种状态

    • pending​​:初始状态,既不是成功也不是失败
    • ​​fulfilled​​:操作成功完成
    • ​​rejected​​:操作失败
  3. 创建 Promise

    const myPromise = new Promise((resolve, reject) => {
     // 异步操作
      if (/* 操作成功 */) {
        resolve('成功的结果');
      } else {
        reject('失败的原因');
      }
    });
    
  4. Promise 方法链

    myPromise
      .then(result => {
        console.log(result); // '成功的结果'
        return '新的值';
      })
      .then(newResult => {
        console.log(newResult); // '新的值'
      })
      .catch(error => {
        console.error(error); // '失败的原因'
      })
      .finally(() => {
        console.log('无论成功失败都会执行');
      });
    

二、Promise 高级用法

  1. Promise 静态方法

    // 所有 Promise 都解决
    Promise.all([promise1, promise2])
      .then(values => console.log(values));
    
    // 任意一个 Promise 解决
    Promise.race([promise1, promise2])
      .then(value => console.log(value));
    
    // 所有 Promise 都完成(无论成功失败)
    Promise.allSettled([promise1, promise2])
      .then(results => console.log(results));
    
    // 立即返回一个已解决的 Promise
    Promise.resolve('立即解决');
    Promise.reject('立即拒绝');
    
  2. Promise 链式调用的错误处理

    doSomething()
      .then(result => doSomethingElse(result))
      .then(newResult => doThirdThing(newResult))
      .catch(error => console.error(error)); // 捕获前面所有 then 中的错误
    
  3. Promise 常见陷阱

    // 错误示例:忘记返回 Promise
    doSomething()
      .then(result => {
        doSomethingElse(result); // 忘记 return
      })
      .then(newResult => {
        // newResult 会是 undefined
      });
    
    // 正确写法
    doSomething()
      .then(result => {
        return doSomethingElse(result); // 显式返回
      });
    

三、async/await 详解

  1. async 函数

    async function myAsyncFunction() {
      return 'Hello'; // 自动包装成 Promise
    }
    
    // 等同于
    function myAsyncFunction() {
      return Promise.resolve('Hello');
    }
    
  2. await 表达式

    async function fetchData() {
      try {
        const response = await fetch('api/data'); // 等待 Promise 解决
        const data = await response.json(); // 再次等待
        return data;
      } catch (error) {
        console.error('获取数据失败:', error);
        throw error; // 可以重新抛出错误
      }
    }
    
  3. async/await 错误处理

    // 方法1:try/catch
    async function getUser() {
      try {
        const user = await fetchUser();
        return user;
      } catch (error) {
        console.error('获取用户失败:', error);
        return null;
      }
    }
    
    // 方法2:catch 处理返回的 Promise
    async function getUser() {
      const user = await fetchUser().catch(error => {
        console.error('获取用户失败:', error);
        return null;
      });
      return user;
    }
    

四、Promise 与 async/await 对比

  1. 代码风格对比

    
    // Promise 风格
    function getData() {
      return fetchData()
        .then(data => processData(data))
        .then(result => saveResult(result))
        .catch(error => handleError(error));
    }
    
    // async/await 风格
    async function getData() {
      try {
        const data = await fetchData();
        const result = await processData(data);
        return await saveResult(result);
      } catch (error) {
        handleError(error);
      }
    }
    
  2. 何时使用哪种?

  • 使用 Promise​​:
    • 需要同时处理多个异步操作(Promise.all/race)
    • 需要精细控制 Promise 链
    • 简单的单次异步操作
  • 使用 async/await​​:
    • 需要顺序执行的异步操作
    • 需要更清晰的错误处理
    • 代码可读性更重要时

五、常见问题与最佳实践

  1. 避免 await 滥用

    // 错误:不必要的顺序执行
    async function processItems(items) {
      for (const item of items) {
        await processItem(item); // 每个都等待,效率低
      }
    }
    
    // 正确:并行处理
    async function processItems(items) {
      await Promise.all(items.map(item => processItem(item)));
    }
    
  2. 顶层 await

    // 模块顶层可以使用 await
    const data = await fetchData();
    console.log(data);
    
    // 注意:需要在 ES 模块中(type="module")
    
  3. async 函数总是返回 Promise

    async function foo() {
      return 'bar';
    }
    
    console.log(foo()); // Promise {<fulfilled>: "bar"}
    
  4. 在循环中使用 await

    // for...of 可以安全使用 await
    async function processArray(array) {
      for (const item of array) {
        await processItem(item);
      }
    }
    
    // 不要在 forEach 中使用 await
    array.forEach(async (item) => {
      await processItem(item); // 不会按预期工作
    });
    

六、实际应用示例

  1. 带超时的 Promise

    function fetchWithTimeout(url, timeout = 5000) {
      return Promise.race([
        fetch(url),
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('请求超时')), timeout)
        )
      ]);
    }
    
  2. 顺序执行异步任务

    async function executeSequentially(promises) {
      const results = [];
      for (const promise of promises) {
        results.push(await promise);
      }
      return results;
    }
    
  3. 重试机制

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

七、总结对比表

在这里插入图片描述

八、最佳实践建议

  • 优先使用 async/await​​ 编写更清晰的代码
  • ​​合理使用 Promise 方法​​(如 all/race)处理并行任务
  • 不要忘记错误处理​​,使用 try/catch 或 .catch()
  • 避免不必要的 await​​,能并行就不要顺序执行
  • 注意 Promise 创建时机​​,避免意外提前执行
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐