JavaScript中Promise讲解和使用方法代码

 更新时间:2026年01月26日 10:18:34   作者:新节  
这篇文章主要介绍了JavaScript中Promise讲解和使用方法的相关资料,Promise是处理异步操作的优秀方案,可以使代码更加简洁、易读、易维护,避免回调地狱和嵌套过深的问题,需要的朋友可以参考下

PromiseJavaScript 异步编程的核心解决方案,它解决了传统回调地狱问题,提供了更优雅的异步控制流。

面试官:谈谈你对 Promise 的理解?

回答:

Promise 用来解决异步回调问题,由于 js
是单线程的,很多异步操作都是依靠回调方法实现的,这种做法在逻辑比较复杂的回调嵌套中会相当复杂;也叫做回调地狱;

promise 用来将这种繁杂的做法简化,让程序更具备可读性,可维护性;promise
内部有三种状态,pending,fulfilled,rejected

pending 表示程序正在执行但未得到结果,即异步操作没有执行完毕,

fulfilled 表示程序执行完毕,且执行成功,

rejected 表示执行完毕但失败;这里的成功和失败都是逻辑意义上的;并非是要报错。

其实,promise 和回调函数一样,都是要解决数据的传递和消息发送问题,promise 中的 then
一般对应成功后的数据处理,catch 一般对应失败后的数据处理。

一、Promise 基础概念

1.1 什么是 Promise?

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

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

1.2 创建 Promise

const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve("操作成功");
    } else {
      reject("操作失败");
    }
  }, 1000);
});

1.3 使用 Promise

promise
  .then((result) => {
    console.log(result); // "操作成功"
  })
  .catch((error) => {
    console.error(error); // "操作失败"
  });

二、Promise 自带方法

2.1 静态方法

Promise.resolve()

创建一个立即解析的 Promise:

Promise.resolve("立即返回").then(console.log); // "立即返回"

Promise.reject()

创建一个立即拒绝的 Promise:

Promise.reject("错误").catch(console.error); // "错误"

Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。等待所有 Promise 完成,或任意一个失败。

“致命伤”:一个失败,全盘皆输

// 假设有三个异步请求:获取用户信息、获取商品列表、获取消息通知
const fetchUserInfo = fetch("/api/user");
const fetchProducts = fetch("/api/products");
const fetchNotifications = fetch("/api/notifications");

Promise.all([fetchUserInfo, fetchProducts, fetchNotifications])
  .then(([userInfo, products, notifications]) => {
    // 只有当三个请求都成功时,才会进入这里
    renderUserPage(userInfo, products, notifications);
  })
  .catch((error) => {
    // 如果任何一个请求失败,就会跳到这里
    console.error("有一个请求失败了:", error);
    showErrorPage("页面加载失败,请重试!");
  });

Promise.race()

返回最先完成的 Promise(无论成功或失败):

const p1 = new Promise((res) => setTimeout(res, 100, "慢"));
const p2 = new Promise((res) => setTimeout(res, 50, "快"));

Promise.race([p1, p2]).then((winner) => {
  console.log(winner); // "快"
});

Promise.allSettled()

为了解决 Promise.all 一个失败,全盘皆输的这个痛点,ES2020 引入了 Promise.allSettled 方法。它的行为更加宽容和稳健:

  • 等待所有:它会等待所有输入的 Promise 都“敲定”(settled),即无论是成功(fulfilled)还是失败(rejected)。
  • 永不失败:Promise.allSettled 自身永远不会被 reject,它总是会成功返回一个数组。
  • 详情可知:返回的数组中的每个对象都包含了每个 Promise 的最终状态和结果(或原因)。

每个结果对象都有两种形态:

  • 成功:{ status: 'fulfilled', value: 结果值 }
  • 失败:{ status: 'rejected', reason: 错误原因 }

如何使用 Promise.allSettled:

Promise.allSettled([fetchUserInfo, fetchProducts, fetchNotifications]).then((results) => {
  // 注意:这里永远不会 catch
  // results 是一个包含三个对象的数组
  const userInfo = results[0].status === "fulfilled" ? results[0].value : null;
  const products = results[1].status === "fulfilled" ? results[1].value : null;
  const notifications = results[2].status === "fulfilled" ? results[2].value : null; // 我们可以针对每个结果进行精细化处理

  if (userInfo && products) {
    // 只要核心数据(用户和商品)还在,就渲染页面
    renderUserPage(userInfo, products, notifications); // notifications 可能是 null
    if (!notifications) {
      showToast("通知获取失败,不影响主要功能");
    }
  } else {
    // 如果核心数据缺失,再显示错误页
    showErrorPage("核心数据加载失败");
  }
});
// 不需要 .catch,因为它永远不会被触发

使用 Promise.allSettled 优势:

  • 体验提升:即使通知接口挂了,用户依然能看到页面主体内容,只会收到一个轻量的提示。
  • 韧性增强:单个接口的失败不会导致整个页面或功能的崩溃。
  • 信息完整:我们可以确切地知道每个任务的执行结果,并据此做出更细致的 UI 响应。

Promise.any()

返回第一个成功的 Promise(忽略失败):

const p1 = Promise.reject("错误1");
const p2 = Promise.resolve("成功");

Promise.any([p1, p2]).then((firstSuccess) => {
  console.log(firstSuccess); // "成功"
});

2.2 实例方法

.then()

处理 Promise 的成功状态:

fetch("/api")
  .then((response) => response.json())
  .then((data) => console.log(data));

.catch()

捕获 Promise 链中的错误:

fetch("/api")
  .then((response) => response.json())
  .catch((error) => console.error("请求失败:", error));

.finally()

无论成功或失败都会执行:

fetch("/api")
  .then((response) => response.json())
  .finally(() => console.log("请求结束"));

三、Promise 高级技巧

3.1 链式调用

function getUser(id) {
  return fetch(`/users/${id}`)
    .then((response) => response.json())
    .then((user) => fetch(`/profile/${user.profileId}`))
    .then((response) => response.json());
}

3.2 错误处理策略

// 方式1:每个 then 后单独 catch
fetch("/api")
  .then((res) => res.json())
  .catch(handleJSONError)
  .then((data) => process(data))
  .catch(handleProcessError);

// 方式2:全局 catch
fetch("/api")
  .then((res) => res.json())
  .then((data) => process(data))
  .catch(handleAnyError);

3.3 取消 Promise

原生 Promise 无法取消,但可以通过封装实现:

function cancellablePromise(promise) {
  let isCancelled = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then((value) => !isCancelled && resolve(value)).catch((error) => !isCancelled && reject(error));
  });

  return {
    promise: wrappedPromise,
    cancel: () => {
      isCancelled = true;
    }
  };
}

3.4 Promise 化回调函数

将回调风格的函数转换为 Promise:

const fs = require("fs");

function readFilePromise(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, (err, data) => {
      if (err) reject(err);
      else resolve(data);
    });
  });
}

四、Promise 与 async/await

4.1 基本转换

// Promise 风格
function getData() {
  return fetch("/api").then((res) => res.json());
}

// async/await 风格
async function getData() {
  const res = await fetch("/api");
  return res.json();
}

4.2 错误处理对比

// Promise
fetch("/api")
  .then((res) => res.json())
  .catch(console.error);

// async/await
try {
  const res = await fetch("/api");
  const data = await res.json();
} catch (err) {
  console.error(err);
}

五、常见问题与解决方案

5.1 Promise 内存泄漏

未处理的 Promise 拒绝会导致内存泄漏:

// 错误示范(未捕获的拒绝)
function riskyOperation() {
  return new Promise((_, reject) => {
    setTimeout(reject, 1000, "错误");
  });
}

// 正确做法
riskyOperation().catch(() => {});

5.2 并行与顺序执行

// 顺序执行
async function sequential() {
  await task1();
  await task2(); // 等待 task1 完成
}

// 并行执行
async function parallel() {
  await Promise.all([task1(), task2()]);
}

六、总结

Promise 的核心优势:

  1. 链式调用:解决回调地狱
  2. 统一错误处理:通过 .catch() 集中管理
  3. 组合能力强Promise.all/race 等实现复杂控制流

最佳实践建议:

  • 始终返回 Promise 链(避免中断)
  • 使用 async/await 提升可读性
  • 不要忘记错误处理
// 终极实践示例
async function getFullData() {
  try {
    const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
    return { user, posts };
  } catch (error) {
    console.error("加载失败:", error);
    throw error; // 向上传递
  }
}

常用方法的区别

方法核心逻辑成功条件失败条件典型使用场景
Promise.all(iterable)“全部成功”
等待所有 Promise 完成
所有 Promise 都成功 (fulfilled)任意一个 Promise 失败 (rejected)并行处理多个相互依赖的任务,如:同时上传多张图片、同时获取多个 API 数据以渲染页面。
Promise.race(iterable)“竞赛”
取最先完成(无论成败)的 Promise 结果
最先完成的 Promise 是成功 (fulfilled)最先完成的 Promise 是失败 (rejected)1. 设置超时/竞速:为异步操作添加超时限制。
2. 从多个最快响应的来源(如 CDN)获取资源。
Promise.allSettled(iterable)“无论成败”
等待所有 Promise 最终敲定 (settled)
总是成功
(返回每个 Promise 的最终状态和结果数组)
不会失败当需要知道每个异步操作的最终结果时,如:批量提交表单,无论单个成功或失败都需要记录日志或进行下一步处理。
Promise.any(iterable)“任一成功”
取最先成功的 Promise 结果
任意一个 Promise 成功 (fulfilled)所有 Promise 都失败 (rejected)1. 寻找最快可用资源:从多个镜像服务器下载同一个文件,使用最先响应的。
2. 提供备用方案,只要一个成功即可。

快速选择指南

当你面对多个异步操作时,可以这样选择:

  • 需要所有操作都成功才能继续 → Promise.all()
  • 只需第一个完成的操作结果(无论成败) → Promise.race()
  • 需要知道每个操作的最终结果(无论成败) → Promise.allSettled()
  • 只需第一个成功的操作结果Promise.any()

总结

到此这篇关于JavaScript中Promise讲解和使用方法的文章就介绍到这了,更多相关js Promise使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript获取客户端计算机硬件及系统等信息的方法

    JavaScript获取客户端计算机硬件及系统等信息的方法

    本文为大家详细介绍下如何使用JavaScript获取客户端计算机硬件及系统等信息,下面有个不错的示例,感兴趣的朋友可以参考下
    2014-01-01
  • JavaScript常问面试题及答案总结大全

    JavaScript常问面试题及答案总结大全

    最近在准备面试,JS的基础问题是每一家公司必问的方面,这篇文章主要介绍了JavaScript常问面试题的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-06-06
  • javascript 实现划词标记划词搜索功能

    javascript 实现划词标记划词搜索功能

    在页面中加上这串代码就行了,同时还有搜索功能。
    2009-10-10
  • 利用前端写一个随机点名网页完整代码

    利用前端写一个随机点名网页完整代码

    在前端开发中,经常需要处理各种随机操作,其中之一是随机点名,这篇文章主要介绍了利用前端写一个随机点名网页的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • js实现简单鼠标跟随效果的方法

    js实现简单鼠标跟随效果的方法

    这篇文章主要介绍了js实现简单鼠标跟随效果的方法,涉及javascript鼠标事件与坐标获取等相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • js中最容易被忽视的事件问题大总结

    js中最容易被忽视的事件问题大总结

    下面小编就为大家带来一篇js中最容易被忽视的事件问题大总结。小编觉得挺不错的,现在分享给大家,也给大家做个参考,一起跟随小编过来看看吧,祝大家游戏愉快哦
    2016-05-05
  • JavaScript 中栈的运用操作步骤

    JavaScript 中栈的运用操作步骤

    栈是一种强大的数据结构,在 JavaScript 中有许多实际应用,从表达式求值到函数调用栈,从图的遍历到括号匹配,栈都发挥了重要作用,这篇文章主要介绍了JavaScript中栈的运用,需要的朋友可以参考下
    2024-11-11
  • JavaScript使用Promise实现并发请求数限制

    JavaScript使用Promise实现并发请求数限制

    本文主要介绍了JavaScript使用Promise实现并发请求数限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 深入理解js函数的作用域与this指向

    深入理解js函数的作用域与this指向

    下面小编就为大家带来一篇深入理解js函数的作用域与this指向。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • 微信小程序 checkbox使用实例解析

    微信小程序 checkbox使用实例解析

    这篇文章主要介绍了微信小程序 checkbox使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09

最新评论