JavaScript异步解决单线程阻塞导致页面卡死的问题,通过事件循环让耗时操作不占用主线程,保障UI流畅响应;它不提速但防停滞,核心是“别停”而非“快”。
JavaScript 是单线程的,主线程一旦被阻塞,页面就卡住、无法响应点击或滚动。所谓“异步”,就是让耗时操作(比如 fetch()、setTimeout()、fs.readFile())不占着主线程等结果,而是先让出控制权,等它做完再通知你——这样页面才不卡。
关键不是“慢”,而是“别停”。异步机制本身不提速,但能保流畅。
while (true) 或同步读大文件,整个页面冻结,连开发者工具都打不开回调函数是“你告诉我做完后干啥”,把处理逻辑直接塞进参数里。它简单、兼容性好,但一串起来就暴露三个硬伤:
getUser(id, function(user) {
getPosts(user.id, function(posts) {
getComments(posts[0].id, function(comments) {
console.log(comments);
});
});
});
if (err) { ... },漏一个就静默失败try/catch:异步回调执行时已脱离原始调用栈,try/catch 捕不到Promise 不是回调的语法糖,而是把异步操作包装成一个有明确状态的对象:pending → fulfilled 或 rejected,且状态不可逆。你不再告诉它“做完干啥”,而是问它“结果是什么”,然后声明式地响应。
getUser(id)
.then(user => getPosts(user.id))
.then(posts => getComments(posts[0].id))
.then(comments => console.log(comments))
.catch(err => console.error('出错了:', err));
.then() 返回新 Promise,天然避免嵌套.then() 中抛错、或返回被 reject 的 Promise,都会被后续最近的 .catch() 捕获Promise.all([p1, p2]) 等全部完成;Promise.race([p1, p2]) 取最快那个;Promise.allSettled() 管它成不成,全等完再说Promise 本身不可取消、没有进度回调、pending 状态无法感知是否卡住——这些是它没解决、也不该解决的问题不是谁淘汰谁,而是看接口契约和维护成本:
fs.readFile(path, callback))仍只接受回调 → 用 util.promisify() 包一层,或手写 new Promise(...) 封装,别裸写回调链button.addEventListener('click', handler))本质是事件机制,不是“异步操作问题”,继续用回调更自然.then() 接口callback 参数,又返回 Promise,调用方会懵,资源可能泄漏最常被忽
略的一点:Promise 构造器里的执行器函数(new Promise((resolve, reject) => {...}))是**同步立即执行**的,里面写错 throw 会直接崩,不是异步错误——这点和 .then() 里的 throw 行为完全不同。