javascript异步是什么_回调函数如何工作【教程】
技术百科
夢幻星辰
发布时间:2026-01-27
浏览: 次 JavaScript异步是单线程事件循环机制,回调函数执行时机由调用方(如setTimeout、fs.readFile)调度;Node.js采用错误优先回调约定(err, data),嵌套过深易致回调地狱,应依场景选择回调、Promise或async/await。
JavaScript 异步不是“多线程”,而是单线程靠事件循环调度回调函数实现非阻塞执行;回调函数本身不异步,它是否延迟执行,完全取决于谁调用它、怎么排队。
回调函数怎么被触发?关键看谁控制执行权
你写的 function(data) { console.log(data) } 只是一个普通函数。它什么时候跑,不由你决定,而由接收它的那个函数(比如 fs.readFile 或 setTimeout)在底层怎么调度:
-
setTimeout把回调推进宏任务队列,等当前同步代码 + 所有微任务(如Promise.then)执行完、调用栈为空时才执行 -
fs.readFile交由 libuv 后台线程读文件,完成后把回调推入 poll 阶段队列,再由事件循环取出 -
array.map(callback)中的callback是同步执行的——没移交控制权,不算异步回调
为什么 err 总是第一个参数?这不是语法,是 Node.js 生态约定
Node.js 所有标准异步 API(如 fs.readFile、http.get)统一采用 “错误优先回调”(error-first callback),形参固定为 (err, data):
-
err不为null或undefined,说明出错了,必须处理,否则后续data.xxx会报Cannot read property 'xxx' of undefined -
try...catch捕获不到回调里的错误,因为回调执行时早已脱离原始调用栈 -
浏览器原生 API(如
setTimeout、addEventListener)不走这个约定,它们没有内置错误通道,出错只能靠window.onerror或console.error
嵌套三层以上就危险:回调地狱的真实代价
当多个异步操作强依赖(A 结果是 B 的参数,B 结果又是 C 的参数),纯回调极易失控:
- 每层都要写
if (err) return,漏一个就可能引发静默崩溃 - 想复用中间结果?得手动存变量,作用域容易混乱
- 想加个“全部完成后再汇总”的逻辑?得自己计数或改结构,极易出错
- 缩进越来越深,调试时连哪层对应哪个请求都难定位
示例中这种写法已属高危:
fs.readFile('a.json', (err, a) => {
if (err)
return;
fs.readFile('b.json', (err, b) => {
if (err) return;
fs.readFile('c.json', (err, c) => {
if (err) return;
console.log(a, b, c);
});
});
});
回调函数不是过时技术,但必须知道它在哪该用、在哪该换
回调仍是底层事实:Promise 和 async/await 底层依然靠它驱动。但它只适合简单、一次性、无强依赖的场景:
- ✅ 适合:
setTimeout、setInterval、fs.readFile(封装层)、DOM 事件监听(addEventListener) - ❌ 不适合:多步骤数据流(登录 → 获取用户 → 获取订单 → 渲染详情)、需集中错误处理、需条件分支或重试逻辑
- ⚠️ 容易忽略的点:回调里修改闭包变量(如
for (var i = 0; i console.log(i), 100))会输出三个3,要用let或立即执行函数
真正卡住人的,从来不是“会不会写回调”,而是没意识到——控制权一旦交出去,你就失去了对执行时机、错误传播和流程走向的直接掌控。
# ai
# 浏览器
# win
# js
# json
# 循环
# Error
# Property
# javascript
# java
# if
# 线程
# 栈
# var
# node
# NULL
# 多线程
# 封装
# 作用域
# map
# try
# catch
# 闭包
# for
# node.js
# 回调函数
# Array
# 形参
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在Golang中捕获JSON序列化错误_Gol
- Win11怎么开启空间音效_Windows11耳机
- Win11右键反应慢怎么办 Win11优化右键菜单
- php能跑在stm32上吗_php在stm32微控
- Win11怎么设置环境变量_Win11配置Path
- How to Properly Use NumPy
- Dapper的Execute方法的返回值是什么意思
- Windows 11如何开启文件夹加密(EFS)_
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Win11怎么解压RAR文件 Win11自带解压功
- 如何将文本文件中的竖排字符串转换为横排字符串
- Win10系统字体模糊怎么办_Windows10高
- Win11如何设置开机问候语 Win11修改登录界
- mac怎么查看wifi密码_MAC查看已连接WiF
- 微信JSAPI支付回调PHP怎么接收_处理JSAP
- 如何在同包不同文件中正确引用 Go 结构体
- 如何诊断并终止卡死的 multiprocessin
- php做exe支持多线程吗_并发处理实现方式【详解
- php命令行怎么运行_通过CLI模式执行PHP脚本
- php8.4xdebug无法调试怎么办_php8.
- Win11怎么设置任务栏图标大小_Windows1
- Win11怎么清理C盘下载文件夹_Win11清理下
- 为什么Go建议使用error接口作为错误返回_Go
- Drupal 中渲染节点时出现 HTML 标签嵌套
- Mac如何查看电池健康百分比_Mac系统信息电源检
- Python列表推导式与字典推导式教程_简化代码高
- Win11怎么设置麦克风权限_允许应用访问Win1
- Mac怎么安装软件_Mac安装dmg与pkg文件的
- PHP怎么接收前端传的时间戳_处理时间戳参数转换技
- Windows10怎么用“讲述人”读屏辅助 Win
- Win11怎么关闭内容自适应亮度_Windows1
- Win11怎么打开注册表_Windows 11注册
- php报错怎么查看_定位PHP致命错误与警告的方法
- Win10系统怎么查看网络连接状态_Windows
- Drupal 中 HTML 链接被重复转义导致渲染
- Python多进程教程_multiprocessi
- 如何用正则表达式精确匹配“start”到“end”
- Windows10怎么查看系统激活状态_Windo
- 如何开启Windows的远程服务器管理工具(RSA
- Windows怎样关闭开始菜单广告_Windows
- 如何使用Golang配置安全开发环境_防止敏感信息
- Win11输入法选字框不见了怎么办_Win11输入
- php下载安装选zip还是msi格式_两种安装包对
- 如何使用正则表达式批量替换重复的 *- 模式为固定
- Linux如何挂载新硬盘_Linux磁盘分区格式化
- LINUX如何开放防火墙端口_Linux fire
- php中self::能调用子类重写的方法吗_静态绑
- 网站内页做seo排名怎么做?
- c++怎么实现高并发下的无锁队列_c++ std:
- Win11怎么连接投影仪_Win11多显示器投屏设


QQ客服