跳转到主内容
极星编程网:以代码为星,赴技术山海!

javascript中Promise如何使用_它如何处理异步操作?

Promise是组织异步状态流的工具,非同步化手段;仅当包装无Promise接口的异步操作(如setTimeout)时需new Promise;对fetch等原生Promise API再封装会破坏错误传播。 Promise 不是“让异步变同步”的工具,而是把异步操作的处理逻辑显式地组织成链式、可捕获的状态流。 它不会消除异步性,但能避免回调地狱,统一错误处理路径。 Promise 构造函数怎么写?什么时候必须 new Promise? 只有当你需要把一个**没有 Promise 接口的异步操作**(比如
setTimeout
、
XMLHttpRequest
、某些老库的 回调函数 )包装成 Promise 时,才需要手动
new Promise
。 常见错误是:对已返回 Promise 的 API(如
fetch()
、
axios.get()
)再包一层
new Promise
,这不仅多余,还容易破坏原生 Promise 的错误传播和取消能力。 ✅ 正确:包装原生回调 API
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
❌ 错误:给 fetch 多套一层
// 别这么写 fetch('/api/data') .then(() => new Promise(resolve => resolve('done'))); // 无意义嵌套
then() 和 catch() 的执行时机与错误穿透规则
then()
接收两个参数:
onFulfilled
和
onRejected
;但更推荐只传第一个,用单独的
catch()
统一处理错误——因为后者会捕获前面所有
then()
中抛出的异常,包括
onFulfilled
内部的
throw
或运行时错误。 立即学习 “ Java免费学习笔记(深入) ”; Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载
catch()
等价于
then(null, onRejected)
只要链中任意环节没被
catch()
拦截,错误会一直向后传递,直到遇到第一个
catch()
或被全局未处理拒绝(
unhandledrejection
)捕获
then(onFulfilled)
内部若
throw
,后续
then()
不会执行,但下一个
catch()
会收到这个错误
Promise.resolve(1) .then(x => { throw new Error('boom'); }) .then(x => console.log('never runs')) .catch(err => console.error(err.message)); // 输出 'boom'
async/await 是语法糖,但它改变了错误处理习惯
async/await
底层仍是 Promise,但写法上更接近同步代码。关键区别在于:
await
后面如果是一个 rejected Promise,会直接抛出错误,必须用
try/catch
捕获,不能靠链式
catch()
。 不加
try/catch
的
await
出错 = 未捕获的 Promise rejection
await Promise.reject('err')
和
throw 'err'
在
try/catch
中行为一致 多个
await
串行执行时,前一个失败,后续不会执行;想并行就用
Promise.all([p1, p2])
async function fetchUser() { try { const res = await fetch('/api/user'); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch (err) { console.error('Fetch failed:', err); throw err; // 如果上层还要处理,记得 re-throw } }
Promise.all() 和 Promise.race() 容易忽略的细节
Promise.all()
要求所有子 Promise 都 fulfilled 才算成功;只要一个 rejected,整个就 rejected —— 即使其他都已完成。如果你需要“不管成败都等全部结束”,得用
Promise.allSettled()
。
Promise.race()
返回第一个 settled(fulfilled 或 rejected)的结果,不是第一个 fulfilled。这点常被误解。
Promise.race([Promise.reject('a'), Promise.resolve('b')])
→ 立即 rejected,值为
'a'
,
'b'
被丢弃
Promise.any()
是新标准(ES2021),返回第一个 fulfilled,全 rejected 才 rejected(带
AggregateError
) 所有这些静态方法都不改变原始 Promise 的状态,只是组合逻辑
const p1 = new Promise(r => setTimeout(() => r('one'), 100)); const p2 = Promise.reject('two'); Promise.race([p1, p2]).catch(console.error); // 输出 'two'
真正难的不是写
then
或
await
,而是判断某个异步操作是否该被 cancel、是否要设置超时、失败后要不要重试——这些逻辑不在 Promise 原语里,得靠
AbortController
、
Promise.race()
包裹或自定义封装来补足。

相关文章