一、Promise 是什么(不是'异步回调的语法糖')
Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。
一句话本质:
Promise 是一个'状态机 + 回调管理器',用来描述'一个未来才会确定结果的值'。
JavaScript Promise 是处理异步操作的对象,代表异步操作的最终完成或失败及其结果值。其状态包括 pending、fulfilled 和 rejected,状态不可逆且只认第一次 resolve。Promise 提供 then、catch、finally、all、race、any 等方法处理异步流程。then 返回新 Promise 实现链式调用,基于微任务机制执行。Promise 无法取消,适合一次性结果和 IO 抽象,复杂流程建议配合 async/await 使用。理解 Promise 状态机、微任务队列及错误传播机制对编写健壮异步代码至关重要。
Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。
一句话本质:
Promise 是一个'状态机 + 回调管理器',用来描述'一个未来才会确定结果的值'。
pending → fulfilledpending → rejectedthen 永远异步执行(微任务)
即使 resolve 是同步调用的
结果值只认第一次
resolve(1)
resolve(2)// 无效
reject(3)// 无效
Promise/A+ & ECMAScript 规范中:
pending fulfilled rejected
✅ 没有 resolved 这个状态
resolved 是一个'动词 / 过程',不是状态
规范里的原话是:
Resolve a promise with x
意思是:
尝试用某个值 x 去'解析(resolve)'Promise
用一句话精确区分(面试级)
resolved 表示 Promise 已经'被处理过',
但它最终可能是 fulfilled,也可能是 rejected
换句话说:
resolved ↓ fulfilled 或 rejected
⚠️ 注意:
一旦进入 resolved 流程,就不再是 pending
'这个 Promise resolve 了'
通常真正意思是:
👉 不是规范用语
Promise.resolve(Promise.reject(1)).then(()=> console.log('fulfilled'),err=> console.log('rejected', err))
rejected(1)
⚠️ 这就是 'resolved ≠ fulfilled' 的最好例子
const promise = new Promise((resolve, reject)=>{
// 异步操作
setTimeout(()=>{
const success = true;
if(success){
resolve('操作成功');
}else{
reject(new Error('操作失败'));
}
},1000);
});
┌─────────────┐
│ pending │
└──────┬──────┘
│
┌──────┴──────┐
│ │
┌───────────┐ ┌───────────┐
│ fulfilled │ │ rejected │
└───────────┘ └───────────┘
{
status:'pending'|'fulfilled'|'rejected',
value: any,
reason: any,
onFulfilledCallbacks:[],
onRejectedCallbacks:[]
}
这不是猜的,是 Promise/A+ 实现的必然结构
then 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 fulfilled 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。then 方法返回的是一个新的 Promise 对象实例;因此可以用链式写法,即 then 的后面再调用另一个 then 方法。
promise.then((result)=>{
console.log('成功:', result);
},(error)=>{
console.log('失败:', error);
});
相当于第二个回调函数指向 reject;catch 方法还有一个作用,就是在执行 resolve 回调时,如果出现错误抛出异常,不会停止运行,而是进入 catch 方法中。
promise .then(result=> console.log(result)).catch(error=> console.error('错误:', error));
finally 方法用于指定不管 Promise 对象最后状态如何,都会执行 finally。finally 方法的回调函数不接收任何参数。这表明 finally 方法里面的操作应与状态无关,不依赖于 Promise 的执行结果。
promise .then(result=> console.log(result)).catch(error=> console.error(error)).finally(()=> console.log('操作结束'));
方法接收一个平行任务。它接收一个数组;数组的每一项都是一个 Promise 对象;当数组的每一项的状态都是 fulfilled 的时候,all 方法的状态会变成 fulfilled。如果有一项状态变成 rejected,那么 all 方法的状态就会变成 rejected
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(values=> console.log(values));// [1, 2, 3]
.catch(error=> console.error(error));
和 all 方法一样,接收的参数是一个每项都是 Promise 的数组。但是与 all 不同的是,当最先执行的事件完成之后,就直接返回 Promise 对象的值,如果第一个 Promise 对象状态是 fulfilled,那自身状态就是 fulfilled。
const p1 = new Promise(resolve=>setTimeout(resolve,500,'快'));
const p2 = new Promise(resolve=>setTimeout(resolve,1000,'慢'));
Promise.race([p1, p2]).then(value=> console.log(value));// "快"
只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。
Promise.any() 跟 Promise.race() 方法很像,只有一点不同,就是 Promise.any() 不会因为某个 Promise 变成 rejected 状态而结束,必须等到所有参数 Promise 变成 rejected 状态才会结束。
Promise.any([p1, p2]).then(value=> console.log(value));
p.then(onFulfilled, onRejected)
then 做了 3 件极其重要的事:
| then 回调返回值 | 新 Promise 状态 |
|---|---|
| 普通值 | fulfilled,值为返回值 |
| Promise | 等这个 Promise |
| thenable 对象 | 按 Promise 解析 |
| throw error | rejected |
| 不写回调 | 值穿透 / 错误冒泡 |
Promise.resolve(1).then(v=> v +1).then(v=> Promise.resolve(v +1)).then(v=>{
throw 'err'
}).catch(e=> console.log(e))
const p2 = p1.then(...)
本质结构:
p1 ──then──▶ p2 ──then──▶ p3
而不是:
p1 └── then └── then └── then
伪代码:
if(x === promise) throw TypeError
if(x is Promise) adopt its state
if(x is object/function&& has then) call then
else resolve(x)
这套规则就是防止循环引用、防止多次 resolve、防止同步 thenable 乱入
console.log(1)
Promise.resolve().then(()=>{
console.log(2)
})
setTimeout(()=>{
console.log(3)
})
console.log(4)
输出顺序:
1 4 2 3
async function foo(){
await bar()
console.log(1)
}
等价于:
function foo(){
return Promise.resolve(bar()).then(()=>{
console.log(1)
})
}
👉 await = Promise.then 的语法糖
throw 等价于 rejectthen 没有 onRejected → 继续向下冒泡.catch() 本质是 .then(null, onRejected)Promise.resolve().then(()=>{
throw new Error('boom')
}).then(()=>{
console.log('never')
}).catch(err=>{
console.log(err.message)
})
Promise.resolve().then(()=>{
setTimeout(()=>{
throw new Error('boom')
})
}).catch(()=>{
console.log('catch?')
})
👉 catch 不会捕获
原因:
Promise 只能捕获 then 链中的同步异常 & 返回的 Promise 异常
不要求背,但必须理解
最小核心能力:
then(onFulfilled, onRejected){
return new Promise((resolve, reject)=>{
// 状态判断
// 回调队列
// 微任务包装
// 返回值处理(Promise Resolution)
})
}
面试官真正想问的是:
❌ 滥用 Promise:
✅ Promise 最适合:
Promise 是现代 JavaScript 异步编程的核心,理解它的工作原理和最佳实践对于编写健壮的异步代码至关重要。
Promise 解决的不是'异步',而是
'用可组合、可推理的方式描述未来值的状态变化'

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online