首页 > 精选要闻 > 宝藏问答 >

问 promise 的用法 异步编程核心方案

2026-11-10 19:41:48
最佳答案

答

Promise 是 JavaScript 里专门用来处理异步操作的对象,它把原本嵌套回调的异步代码改成链式调用的写法,解决回调地狱问题,同时统一异步操作的状态管理,让异步任务可以明确区分成功失败两种结果,还能配合异步并发控制,是现代前端异步编程的基础,async await 本质也是基于 Promise 语法糖。Promise 一共有三种固定状态,分别是 pending 进行中 fulfilled 已成功 rejected 已失败,状态一旦从 pending 转变为 fulfilled 或者 rejected 之后就永久锁定,不能再次切换,这是它最核心的设计特点,也是理解所有用法的基础。

基础创建与状态流转

new Promise 接收一个执行器函数,这个执行器会立刻同步执行,执行器里面有两个形参 resolve 和 reject,调用 resolve 就会把状态改成 fulfilled,并且把传入的值作为成功结果,调用 reject 就会把状态改成 rejected,把传入的值作为失败原因。

基础示例写法

const p = new Promise ((resolve, reject) => {

// 异步任务写在这里

setTimeout (() => {

resolve ("成功数据")

}, 1000)

})

实例核心方法

then 接收两个可选回调,第一个回调对应 fulfilled 状态,拿到成功返回值,第二个回调对应 rejected 状态,拿到失败原因,then 执行之后会返回一个全新的 Promise 对象,这就是链式调用可以连续写 then 的根本原因。

catch 本质等同于 then 的第二个参数,专门用来捕获前面链路里抛出的错误或者 reject,一般推荐链式末尾统一写 catch,不用每个 then 都写失败回调。

finally 不管 Promise 最终是成功还是失败,都会执行里面的回调,它不接收参数,也不会修改原 Promise 的返回值,常用于关闭加载状态清理定时器这类收尾操作。

静态方法清单

Promise.all 接收 Promise 组成的数组,全部成员都成功,才会返回成功,结果是所有成功值组成的数组,只要任意一个失败,立刻整体失败,返回第一个失败的原因,适合多个请求全部完成之后再执行后续逻辑。

Promise.race 接收 Promise 数组,只要任意一个 Promise 率先完成不管成功还是失败,就以这个最先完成的结果作为最终结果,常用来做请求超时竞速。

Promise.allSettled 接收 Promise 数组,等待所有 Promise 全部落定,不管成功失败,最后返回每一项的状态和对应结果,不会因为单个失败中断,适合需要拿到全部任务执行结果的场景。

Promise.any 接收 Promise 数组,只要任意一个 Promise 成功就返回该成功结果,如果全部都失败,才会抛出聚合错误,和 all 逻辑刚好相反。

Promise.resolve 快速创建一个已经成功状态的 Promise,可以传入值,如果传入本身就是 Promise,会直接返回这个 Promise。

Promise.reject 快速创建一个已经失败状态的 Promise,传入的值就是失败原因。

链式调用与错误穿透

then 里面如果回调返回普通值,下一层 then 就会收到这个普通值,如果回调返回新 Promise,下一层 then 会等待这个新 Promise 落定之后再执行。链路中间任意位置抛出异常,错误会一直向下穿透,直到遇到 catch 捕获,如果没有 catch,就会变成未捕获的 Promise 错误,控制台抛出 unhandledrejection 报错。

Promise 和 async await 的关联

async 函数默认返回 Promise 对象,函数内部 return 的值会自动包装成 fulfilled 状态 Promise,函数内部抛出错误,async 函数就会变成 rejected 状态,await 只能等待 Promise 落定,await 后面如果是 rejected 的 Promise,必须搭配 try catch 捕获错误,本质没有脱离 Promise 机制。

常见坑点说明

第一 执行器内部代码是同步立即执行,不是异步,很多新手误以为 new Promise 之后里面代码延迟运行。

第二 状态不可逆,一旦 resolve 之后,后面再写 reject 不会生效。

第三 then 里面如果没有返回值,下一个 then 拿到的是 undefined。

第四 Promise.all 里面某个任务失败会直接终止,不会等待其余任务执行完毕。

【常见问题】

问题 1 Promise 的三种状态为什么不能逆向修改

回答 1 Promise 设计成单向状态流转,pending 只能转向 fulfilled 或者 rejected,落定之后锁定,这样可以保证异步结果唯一,避免同一个 Promise 多次触发成功或者失败回调,保证链式调用逻辑稳定。

问题 2 Promise 链式调用为什么可以连续写多个 then

回答 2 因为每一次调用 then 都会返回一个全新 Promise 对象,新 Promise 会等待当前 then 回调执行完成,如果回调返回 Promise 就继续等待它落定,所以可以持续串联后续逻辑。

问题 3 Promise.all 和 Promise.allSettled 核心差别是什么

回答 3 Promise.all 只要有一个 Promise 失败整体立刻失败,Promise.allSettled 会等待全部 Promise 落定,保留每一项成功或者失败的完整信息,不会因为单个失败中断整体任务。

问题 4 Promise 未捕获 reject 报错是什么原因

回答 4 当 Promise 进入 rejected 状态,整条链路没有写 catch 捕获错误,浏览器或者 Node 环境就会抛出未捕获拒绝错误,需要在链式末尾增加 catch 或者使用 try catch 配合 await 处理。

【免责申明】

本文内容基于 JavaScript 标准规范进行技术讲解,仅作为学习参考,不同浏览器和 Node 版本对 Promise 相关 API 支持存在差异,实际项目开发请结合运行环境测试,本文不保证适配所有特殊业务场景,不构成生产环境部署的绝对技术承诺。