Promise 是标准化的异步状态容器,解决回调地狱问题,具有 pending/fulfilled/rejected 三种不可逆状态;async/await 是其语法糖,但受限于执行上下文与错误处理机制。

Promise 本质是啥,为什么不能直接用回调函数嵌套
Promise 不是语法糖,而是一个标准化的异步状态容器。它解决的核心问题是“回调地狱”——比如连续发起三个 API 请求,每个都依赖上一个的返回结果,用纯回调写出来就是 getData(cb1) → cb1 里调 getData2(cb2) → cb2 里再调 getData3(cb3),缩进深、错误难捕获、流程难复用。
Promise 把“等待结果”这个动作封装成对象,有三种固定状态:pending(进行中)、fulfilled(成功)、rejected(失败),且状态不可逆。一旦变为后两者,就再也无法更改。
常见误用:
- 把同步代码包进
new Promise()却不调resolve()或reject(),导致永远卡在pending - 在
.then()里忘记return,后续链式调用拿到的是undefined,不是上一步的值 - 用
.then(success, fail)双参数形式,但fail无法捕获success函数内部抛出的错误(应该用.catch())
async/await 是 Promise 的语法糖,但不是所有地方都能替代
async 函数返回值一定是 Promise 对象,哪怕你 return 123,实际等价于 return Promise.resolve(123)。所以不能把它当普通函数用,比如直接赋值给事件回调或定时器回调,除非你明确处理 Promise。
立即学习“Java免费学习笔记(深入)”;
关键限制:
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。它不是新的编程语言,而是一种使用现有标准的新方法,最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容,不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。《php中级教程之ajax技术》带你快速
-
await只能在async函数内部使用,不能出现在顶层模块作用域(ESM 中可用top-level await,但 Node.js 14+ / 浏览器支持不一) -
await后面如果不是 Promise,会自动包装成Promise.resolve(value);如果是 Promise,则等待其 settle -
await遇到 rejected Promise 会抛出异常,必须用try/catch捕获,不能靠外层.catch()
async function fetchUser() {
try {
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const user = await res.json();
return user;
} catch (err) {
console.error('获取用户失败:', err.message);
throw err; // 不 throw 的话,调用方 .catch() 接不到
}
}
Promise.all 和 Promise.race 的实际选择逻辑
这两个方法常被误认为“并发请求工具”,其实它们定义的是**组合语义**:
-
Promise.all([p1, p2, p3]):全部成功才 resolve,任意一个 reject 就立刻 reject(“全胜或全败”) -
Promise.race([p1, p2, p3]):谁先 settle(无论 fulfill/reject),就以它的结果为准(“抢答模式”)
典型场景:
- 加载多个资源(如图片 + 配置 + 用户信息),缺一不可 → 用
Promise.all - 实现超时控制:把业务请求和
setTimeout包装的 Promise 一起传给Promise.race→ 谁快谁赢 - 需要 fallback 时,比如先试本地缓存(快但可能失效),再备选网络请求 →
Promise.race([cachePromise, networkPromise])
const timeout = (ms) => new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), ms)
);
Promise.race([
fetch('/api/data'),
timeout(5000)
]).catch(err => console.error(err.message)); // 5秒内没响应就报错
容易被忽略的错误传播和调试盲区
异步错误不会冒泡到同步上下文。比如你在 setTimeout(() => { throw new Error('boom') }, 0) 里抛错,或者在 Promise.then(() => { throw new Error('boom') }) 里抛错,若没配 .catch() 或 try/catch,就会变成未捕获异常(unhandled rejection),Node.js 会打印警告,浏览器可能静默失败。
调试建议:
- 始终为 Promise 链末尾加
.catch(console.error),或在async函数外层包try/catch - Node.js 中启用
process.on('unhandledRejection', (reason, promise) => { ... })捕获漏网之鱼 - Chrome DevTools 的
Async Stack Trace开关要打开,否则 await 后的报错堆栈只显示到await行,看不到源头 - 不要在
.then()里写console.log就以为执行了——如果前面 Promise 已经 reject 且没 catch,.then根本不会进
最麻烦的情况是:Promise 构造函数里抛了同步错误(比如 JSON.parse 失败),但没写 reject,也没 try/catch,这会导致错误直接崩掉整个脚本,而不是变成 rejected Promise。










