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秒执行"));
相关推荐
golang学习记11 分钟前
从0死磕全栈之Next.js 中的错误处理机制详解(App Router)
前端
力Mer12 分钟前
console.log()控制台异步打印与对象展开后不一致问题
前端·javascript
WillaWang17 分钟前
Liquid:在assign定义变量时使用allow_false
前端
2401_8315017318 分钟前
Python学习之Day05学习(定制数据对象,面向对象)
前端·python·学习
GISer_Jing29 分钟前
得物前端二面潜在问题详解
前端·javascript·面试
飞天巨兽1 小时前
HTTP基础教程详解
前端·网络·网络协议·http
FIN66681 小时前
昂瑞微IPO前瞻:技术破局高端射频模组,国产替代第二波浪潮下的硬科技突围
前端·科技·搜索引擎·产品运营·创业创新·制造·射频工程
玉树临风江流儿2 小时前
Cmake使用CPack实现打包
java·服务器·前端
xier1234563 小时前
一个全新的react表格组件方案
前端
未来之窗软件服务3 小时前
从东方仙盟筑基期看 JavaScript 动态生成图片技术-东方仙盟
开发语言·javascript·仙盟创梦ide·东方仙盟·图片技术