Promise 的场景和最佳实践

Promise 是 JavaScript 中用于处理异步操作的一个对象,它表示一个异步操作的最终结果,可能是成功或失败,Promise 通常用于处理异步操作,比如从服务器获取数据读取文件定时任务用户操作

基本的使用

js 复制代码
const myPromise = new Promise((resolve, reject) => {
  const success = true;
  
  if(success) {
    resolve("操作成功!");
  } else {
    reject("操作失败。");
  }
});

myPromise
  .then(result => console.log(result))  // 如果 Promise 成功
  .catch(error => console.log(error));  // 如果 Promise 失败

常见的用法和示例

  1. 链式调用 (then)

Promise 支持链式调用,可以在一个 then 后接着另一个 then,处理不同的异步操作。

js 复制代码
new Promise((resolve, reject) => {
  setTimeout(() => resolve("第一个操作成功!"), 1000);
})
.then(result => {
  console.log(result);  // 输出: 第一个操作成功!
  return "第二个操作成功!";
})
.then(result => {
  console.log(result);  // 输出: 第二个操作成功!
});
  1. 多个 Promise 的并行执行 (Promise.all)

如果你有多个独立的异步操作,并且你希望它们并行执行,可以使用 Promise.all,它会等到所有的 Promise 都完成后再继续执行。

js 复制代码
const promise1 = new Promise(resolve => setTimeout(() => resolve("操作1完成"), 1000));
const promise2 = new Promise(resolve => setTimeout(() => resolve("操作2完成"), 2000));

Promise.all([promise1, promise2])
  .then(results => {
    console.log(results);  // 输出: ["操作1完成", "操作2完成"]
  });
  1. 处理单个 Promise 的异常 (catch)

catch 方法是用来捕捉 Promise 中的异常的,它可以让你在异步操作失败时处理错误。

js 复制代码
new Promise((resolve, reject) => {
  setTimeout(() => reject("操作失败!"), 1000);
})
.then(result => {
  console.log(result);
})
.catch(error => {
  console.log("捕获错误:", error);  // 输出: 捕获错误: 操作失败!
});
  1. Promise 的竞态条件 (Promise.race) Promise.race 会返回第一个完成的 Promise,不管它是成功还是失败。
js 复制代码
const promise1 = new Promise(resolve => setTimeout(() => resolve("操作1完成"), 2000));
const promise2 = new Promise(resolve => setTimeout(() => resolve("操作2完成"), 1000));

Promise.race([promise1, promise2])
  .then(result => {
    console.log(result);  // 输出: 操作2完成
  });
  1. 串联多个异步操作 (async/await)

async/awaitPromise 的语法糖,使得异步操作看起来像是同步的。

js 复制代码
async function run() {
  try {
    const result1 = await new Promise(resolve => setTimeout(() => resolve("操作1完成"), 1000));
    console.log(result1);
    const result2 = await new Promise(resolve => setTimeout(() => resolve("操作2完成"), 1000));
    console.log(result2);
  } catch (error) {
    console.log("捕获错误:", error);
  }
}

run();

async 函数中,你可以使用 await 等待 Promise 的结果,这使得异步代码更简洁易读。

在实际项目中使用

  1. API 请求

在开发前端应用时,向后端请求数据是最常见的异步操作。通常会使用 Promise 来处理 API 请求, 通常会使用 async/await 来简化这类代码。

js 复制代码
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log("数据:", data);
  } catch (error) {
    console.error("获取数据失败:", error);
  }
}
  1. 多个异步操作并行执行 (Promise.all)

这种方式比一一等待每个请求更加高效,尤其是在多个请求之间没有依赖关系时

例如,加载多个 API 数据:

js 复制代码
const fetchData1 = fetch('https://api.example.com/data1').then(res => res.json());
const fetchData2 = fetch('https://api.example.com/data2').then(res => res.json());

Promise.all([fetchData1, fetchData2])
  .then(([data1, data2]) => {
    console.log("数据1:", data1);
    console.log("数据2:", data2);
  })
  .catch(error => {
    console.error("加载数据失败:", error);
  });
  1. 串联多个异步操作 (then)

一个异步操作完成后再执行下一个操作,这时可以使用 then 链式调用来处理。

例如,先提交表单数据,再获取结果:

js 复制代码
function submitForm(data) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟异步表单提交
      if (data) resolve("表单提交成功");
      else reject("表单提交失败");
    }, 1000);
  });
}

submitForm({ name: 'John', age: 30 })
  .then(result => {
    console.log(result);  // 输出: 表单提交成功
    return fetch('https://api.example.com/result');  // 提交成功后获取结果
  })
  .then(response => response.json())
  .then(data => console.log("结果数据:", data))
  .catch(error => console.error("错误:", error));
  1. 处理复杂的异步控制流async/await

async/awaitPromise 的语法糖,使得异步代码看起来像同步代码,简化了逻辑结构,尤其是处理多层嵌套的异步调用时非常有用。

例如,用户登录后执行后续操作:

js 复制代码
async function loginUser(credentials) {
  try {
    const loginResponse = await fetch('https://api.example.com/login', {
      method: 'POST',
      body: JSON.stringify(credentials),
    });
    const loginData = await loginResponse.json();
    
    if (loginData.success) {
      const userProfile = await fetch('https://api.example.com/user/profile');
      const profileData = await userProfile.json();
      console.log("用户资料:", profileData);
    } else {
      console.error("登录失败");
    }
  } catch (error) {
    console.error("发生错误:", error);
  }
}
  1. 错误处理和重试机制

在项目中,经常会遇到某些操作可能会失败的情况,比如网络请求失败。你可以使用 catch 来捕获错误,甚至设置重试机制。

例如,添加重试机制:

js 复制代码
function fetchWithRetry(url, retries = 3) {
  return new Promise((resolve, reject) => {
    function attempt() {
      fetch(url)
        .then(response => {
          if (!response.ok) throw new Error("请求失败");
          return response.json();
        })
        .then(resolve)
        .catch(error => {
          if (retries > 0) {
            console.log(`重试剩余次数: ${retries}`);
            retries--;
            attempt();  // 重试
          } else {
            reject(error);  // 最终失败
          }
        });
    }
    attempt();
  });
}

fetchWithRetry('https://api.example.com/data')
  .then(data => console.log("数据:", data))
  .catch(error => console.error("最终错误:", error));
  1. 动画和延时操作 有时你需要在执行一系列操作时,插入一些动画或延时操作。你可以利用 Promise 来实现这一需求。

例如,延时执行:

js 复制代码
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

delay(1000)  // 延迟1秒
  .then(() => console.log("1秒后执行"))
  .then(() => delay(2000))  // 再延迟2秒
  .then(() => console.log("再过2秒执行"));
相关推荐
折翅嘀皇虫3 小时前
fastdds.type_propagation 详解
java·服务器·前端
Front_Yue3 小时前
深入探究跨域请求及其解决方案
前端·javascript
wordbaby3 小时前
React Native 进阶实战:基于 Server-Driven UI 的动态表单架构设计
前端·react native·react.js
抱琴_3 小时前
【Vue3】我用 Vue 封装了个 ECharts Hooks,同事看了直接拿去复用
前端·vue.js
风止何安啊3 小时前
JS 里的 “变量租房记”:闭包是咋把变量 “扣” 下来的?
前端·javascript·node.js
Danny_FD4 小时前
用 ECharts markLine 标注节假日
前端·echarts
程序员西西4 小时前
SpringBoot无感刷新Token实战指南
java·开发语言·前端·后端·计算机·程序员
烛阴4 小时前
Luban集成CocosCreator完整教程
前端·typescript·cocos creator
有点笨的蛋4 小时前
深入理解 JavaScript 原型机制:构造函数、原型对象与原型链
前端·javascript
o***74174 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端