javascript的异步编程是什么_回调函数是如何工作的【教程】

8次阅读

javaScript异步编程本质是避免线程阻塞,通过回调函数接收后台任务结果;回调执行时机由调用方调度决定,node.js采用错误优先约定,多层嵌套易导致回调地狱。

javascript的异步编程是什么_回调函数是如何工作的【教程】

javascript 异步编程不是让代码“同时跑多个任务”,而是让主线程不被耗时操作卡住——fs.readFilefetchsetTimeout 这些操作一调用就立刻返回,真正干活(读磁盘、发请求、计时)由浏览器或 Node.js 底层在后台处理,结果好了再“通知你”,而这个“通知方式”,最原始也最核心的就是回调函数

回调函数怎么被调用?谁说了算?

回调函数本身只是个普通函数,它是否异步、何时执行,完全取决于它被传给了谁、以及那个函数内部怎么调度它。

  • setTimeout 把回调塞进宏任务队列,等当前所有同步代码和所有 promise.then(微任务)执行完、调用空了,才拿出来执行
  • fs.readFilenode.js)由 libuv 在后台线程读文件,完成后把回调推入事件循环poll 阶段队列,再调度执行
  • Array.map(callback) 中的 callback同步执行的——它根本没移交控制权,不算异步回调

为什么 err 总是第一个参数?漏判会怎样?

这不是 JavaScript 语法要求,而是 Node.js 生态的硬性约定:所有标准异步 API(如 fs.readFilehttp.get)都采用“错误优先回调”((err, data))。目的是让错误路径可预测、可集中处理。

  • 如果 err 不为 NULLundefined,说明操作失败,data 很可能不可用甚至为 undefined
  • 漏掉 if (err) { return; },后续直接访问 data.xxx 就会报 Cannot read Property 'xxx' of undefined
  • try/catch 捕获不到回调里的错误,因为回调执行时早已脱离原始调用
fs.readFile('./config.json', 'utf8', (err, data) => {   if (err) {     console.error('读取失败:', err.message);     return; // 必须 return,否则下面代码仍会执行   }   const config = json.parse(data); // 此处才安全使用 data   console.log(config.host); });

回调地狱长什么样?3 层嵌套就是危险信号

当多个异步操作强依赖(A 的结果是 B 的输入,B 的结果又是 C 的输入),纯回调极易形成“金字塔式缩进”,结构脆弱、调试困难、复用成本高。

立即学习Java免费学习笔记(深入)”;

  • 每层都要重复写 if (err) return,漏一处就崩
  • 中间状态难传递:想把 A 的 userId 传给 C,要么闭包捕获,要么提成全局变量,污染作用域
  • 无法用 returnthrow 控制外层流程——回调里的 return 只退出自己那层
  • 超过 3 层嵌套,就该考虑用 Promiseasync/await 重构
requestData("/api/user", (err, userData) => {   if (err) return console.error("用户请求失败", err);   requestData(`/api/orders?userId=${userData.id}`, (err, orderData) => {     if (err) return console.error("订单请求失败", err);     requestData(`/api/orderDetail?orderId=${orderData.id}`, (err, detailData) => {       if (err) return console.error("详情请求失败", err);       console.log(detailData);     });   }); });

回调函数的难点从来不在语法,而在于你是否清楚它会在哪条线程、哪个时刻、带着什么变量值被调用。一旦涉及多结果组合、超时控制、并发限制,光靠回调就容易失控——这不是它错了,是它已经完成了自己的历史使命。

text=ZqhQzanResources