Promise 是需用 new Promise() 构造的对象,执行器函数中必须显式调用 resolve/reject;.then() 链式返回新 Promise,错误需 .catch() 或 try/catch 捕获;async/await 是语法糖但需在 async 函数内使用;Promise 状态不可逆,未处理 rejection 会静默失败。
new Promise() 包裹异步操作Promise 不是语法糖,而是一个对象,必须用 new Promise() 构造,且传入一个执行器函数(executor),它接收 resolve 和 reject 两个参数。常见错误是忘记 return、漏掉 reject、或在同步错误中没调用 reject。
正确示例:
const fetchUser = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = Math.random() > 0.3;
if (success) {
resolve({ id: 123, name: 'Alice' });
} else {
reject(new Error('Network failed'));
}
}, 500);
});
};
resolve 和 reject 必须显式调用,不会自动触发setTimeout、fetch)必须放在 executor 内部,不能“先执行再包 Promise”try/catch + reject
.then() 和 .catch() 链式调用:每个 .then() 返回新 Promise链式调用的关键在于:每个 .then() 的返回值会成为下一个 .then() 的输入;如果返回的是 Promise,则自动等待其完成;如果抛错或返回 Promise.reject(),后续 .then() 会被跳过,直到遇到 .catch()。
避免回调地狱的核心就在这里:把嵌套变成扁平链。
立即学习“Java免费学习笔记(深入)”;
fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => filterActive(posts))
.then(filtered => saveToCache(filtered))
.catch(err => console.error('Failed at:', err.message));
.then() 里写 if/else 分支并混用 return 和 throw —— 容易漏掉错误路径.catch() 只捕获前面 Promise 链中的 rejection,不捕获 .then() 内部的同步异常(除非你手动 throw)Promise.all([p1, p2, p3]),别串行调用三次 .then()
await 必须在 async 函数内很多人写 await fetchUser() 却忘了外层函数加 async,结果报错 Uncaught SyntaxError: await is only valid in async function。
正确写法:
const loadProfile = async () => {
try {
const user = await fetchUser();
const posts = await fetchPosts(user.id);
return { user, posts };
} cat
ch (err) {
console.error('Load failed:', err);
throw err; // 不要静默吞掉错误,下游可能依赖这个 rejection
}
};
await 后面必须是 Promise(或 thenable),否则直接返回原值try/catch 捕获的是 Promise rejection,不是所有 JS 异常(比如 undefined.foo() 还是同步报错)await:for-of + await 是串行,想并行得用 Promise.all(…map(async …))
Promise 一旦 resolve 或 reject,状态就锁定,再次调用另一个方法无效。更危险的是:未被 .catch() 或 try/catch 捕获的 rejection,在现代浏览器和 Node.js 中会触发 unhandledrejection 事件,但默认不报错 —— 你的请求失败了,控制台却没提示。
window.addEventListener('unhandledrejection', e => console.error(e.reason));
() => { doSomething(); } 就不返回 Promise,导致链中断reject 最好传 Error 实例,而不是字符串 —— 方便堆栈追踪和统一错误处理