当前位置: 首页 > news >正文

JavaScript 回调函数(Callbacks)

本文全面讲解 JavaScript 回调同步 / 异步回调、错误优先模式、回调地狱、Promise 诞生原因是前端异步编程核心基础。为什么 JavaScript 不会等待当你设置定时器、发起网络请求、监听点击时代码为何能继续运行而不卡住console.log(Before timer) setTimeout(function() { console.log(Timer fired!) }, 1000) console.log(After timer) // 输出 // Before timer // After timer // 1秒后Timer fired!答案就是回调callback把函数传给另一个函数告诉它 “做完后调用我”。MDN 定义回调函数是被当作参数传入另一个函数并在外部函数内部被调用的函数。回调支撑了 JavaScript 所有异步逻辑事件、定时器、网络请求全都依赖它。本文你将学到什么是回调为什么 JS 需要回调同步回调 vs 异步回调回调与高阶函数的关系常见回调模式事件、定时器、数组方法错误优先回调模式Node 规范回调地狱厄运金字塔如何逃离回调地狱Promise 为何被发明前置知识事件循环、高阶函数。什么是回调回调是作为参数传给另一个函数并在之后被执行的函数。由另一个函数决定何时或是否执行它。// greet 是回调函数 function greet(name) { console.log(Hello, ${name}!) } // processUserInput 接收回调 function processUserInput(callback) { const name Alice callback(name) // 回调执行 } processUserInput(greet) // Hello, Alice!“回调” 的含义做完事情后再叫你。像餐厅叫号器“桌位好了我叫你”。回调就是普通函数只是使用方式特殊传给别人晚点执行。回调可以是匿名的// 具名函数 button.addEventListener(click, handleClick) // 匿名函数 button.addEventListener(click, function() { console.log(Clicked!) }) // 箭头函数 button.addEventListener(click, () { console.log(Clicked!) })具名函数更易调试、可复用。餐厅叫号器类比你下单 → 调用函数并传入回调拿到叫号器 → 函数注册回调你去坐下 → 代码继续执行非阻塞叫号器响 → 异步操作完成取餐 → 回调执行核心不等待不阻塞这是 JS 保持快速的原因。回调与高阶函数高阶函数接收函数作为参数 或 返回函数回调被传给高阶函数的那个函数const numbers [1,2,3] numbers.forEach((num) { // 箭头函数 回调 console.log(num * 2) })map/filter/forEach/reduce/sort/find全都是高阶函数都在使用回调。同步回调 vs 异步回调同步回调立即执行阻塞调用期间完成。const doubled [1,2,3].map(num num * 2)常见场景数组方法、字符串替换、对象遍历。异步回调稍后执行非阻塞通过事件循环运行。setTimeout(() { console.log(异步) }, 0)常见场景定时器、事件监听、网络请求、Node I/O。对比表表格方面同步回调异步回调执行时机立即执行稍后执行事件循环是否阻塞是否示例map/filter/forEachsetTimeout/addEventListener/fetch错误处理try/catch 有效try/catch 无效返回值可返回通常被忽略关键区别错误处理// 同步try/catch 有效 try { [1,2,3].forEach(num { if (num 2) throw new Error(Found 2!) }) } catch (e) { console.log(捕获到, e.message) } // 异步try/catch 无效 try { setTimeout(() { throw new Error(异步错误) }, 100) } catch (e) { // 永远不会执行 }原因异步回调运行时try/catch早已执行完毕不在同一个调用栈。回调与事件循环的工作流程代码执行注册异步回调Web API 处理异步操作定时器 / 网络 / I/O操作完成 → 回调进入任务队列调用栈空 → 事件循环把回调推入栈执行示例执行顺序console.log(1) setTimeout(()console.log(2), 0) setTimeout(()console.log(3), 0) console.log(4) // 输出1 → 4 → 2 → 3常见回调模式1. 事件处理最常用button.addEventListener(click, (e) { console.log(点击, e.target) })2. 定时器setTimeout(() {}, 2000) setInterval(() {}, 1000)3. 数组迭代同步回调forEach遍历map转换filter筛选find查找第一个reduce聚合4. 自定义回调function fetchData(id, callback) { setTimeout(() { callback({ id, name: Alice }) }, 1000) }错误优先回调模式Node 风格Node.js 统一异步错误处理规范第一个参数永远是错误第二个是结果function callback(error, result) { ... }示例fs.readFile(config.json, utf8, (err, data) { if (err) { console.error(读取失败, err) return } console.log(data) })优点统一、强制检查错误、早期返回、适配异步无法捕获异常。回调地狱厄运金字塔多层异步依赖导致深度嵌套代码向右无限延伸getUser(userId, (err, user) { verifyPassword(user, pw, (err, valid) { getProfile(user.id, (err, profile) { getSettings(user.id, (err, settings) { renderDashboard(...) }) }) }) })问题难读、难调试、难维护、重复错误处理、作用域混乱。逃离回调地狱的 5 种方法具名函数拆平嵌套早期返回减少缩进模块化拆分流程控制库async.js历史方案Promise async/await现代标准方案Promise 就是为解决回调问题而生。回调常见错误多次调用回调同步异步混用Zalgo 问题丢失 this 上下文箭头函数 /bind/self 解决不处理错误历史为什么 JS 用回调1995 年 JS 诞生为网页交互设计单线程不能阻塞 DOM回调 非阻塞解决方案2015 ES6 Promise 标准化2017 ES8 async/await 普及回调仍是基石Promise/async/await 底层都是回调。一、核心概念回调函数 Callback同类钩子函数、处理函数、监听器、then 回调高阶函数 Higher-Order Function同类函数式编程、函数作为参数、闭包事件循环 Event Loop同类调用栈、任务队列、宏任务、微任务同步回调同类map/filter/forEach/reduce/sort异步回调同类定时器、事件、网络、I/O、Promise.then二、模式与规范错误优先回调 Error-First Callback同类Node 风格回调、errback、异常传递模式回调地狱 Callback Hell同类厄运金字塔、嵌套回调、深度嵌套Zalgo 问题同类同步异步不一致、非确定性执行、时序 Bug三、解决方案Promise同类Future、Deferred、异步状态容器async/await同类同步写法异步执行、协程、Generatorasync.js同类流程控制库、串行 / 并行 / 瀑布流四、相关机制this 丢失同类作用域、上下文、bind/call/apply、箭头函数闭包同类变量捕获、延迟执行、私有状态非阻塞 I/O同类异步 I/O、事件驱动、单线程并发
http://www.rkmt.cn/news/1296829.html

相关文章:

  • CircuitPython库包管理利器:circup bundle-remove命令详解与实战
  • 香港运输署:運輸策劃及設計手冊 2026
  • Synopsys VIP调试利器:活用save_mem与load_mem实现Memory数据快照与比对
  • 惠普战99新机踩坑记:Win11专业版下彻底关闭Hyper-V,解决VMware 16.2运行Ubuntu键盘卡顿
  • taotoken如何为ubuntu上的ai应用提供稳定多模型api支持
  • 冰狐冷冻油替换开利/汉钟/约克/比泽尔/麦克维尔/复盛/顿汉布什/特灵/莱富康/克莱门特/神钢/丹佛斯/日立/冰轮/冰山制冷压缩机冷冻油平替型号全表 - 新闻快传
  • 联想刃7000k BIOS深度解锁终极指南:免费释放硬件性能
  • 实测Taotoken多模型聚合路由能力,在不同负载下的响应延迟体感
  • Taotoken用量看板与账单追溯功能在项目复盘中的实际价值
  • 电赛信号分析不止于FFT:用STM32F407的ADC-DMA与加窗技术提升THD测量稳定性的实操指南
  • 告别DLL缺失困扰:Visual C++运行库一站式解决方案
  • 告别Selenium!用影刀RPA零代码搞定网页自动化与数据抓取(附实战案例)
  • Doramagic工具箱:模块化脚本集的设计哲学与工程实践
  • 比特币钱包密码恢复终极指南:如何找回丢失的密码和助记词
  • YouTube 视频翻译中文:基于 Whisper + FFmpeg 的自动化流水线实战
  • 探索霞鹜文楷:一款让中文排版更优雅的开源字体
  • Arm Mali Midgard GPU架构解析与优化实践
  • 通过DrissionPage爬取某获客平台内容
  • 初创团队如何利用Taotoken以最小成本启动AI产品开发
  • 选对GEO监测优化系统,品牌AI推荐率提升5倍:五款主流平台对比 - 新闻快传
  • YOLOv5/v7改进系列——融合EfficientNetV2主干网络的轻量化部署实践
  • 三步搞定Windows磁盘空间不足:WinDirStat终极清理方案
  • CST软件利用电流钳(current probe)测试实现以太网口的RE仿真
  • 永久免费无套路!网慕安 ERMS-Agent,重新定义中小企业安全新标准
  • 12000㎡智造基地,赋能服装工厂自动化务实升级
  • 别再只用普通GCN了!手把手教你用CompGCN搞定知识图谱链接预测(附PyTorch代码)
  • 充电桩串口屏选型与开发实战:基于大彩屏的HMI设计指南
  • Linux内核模块化驱动开发:从框架原理到嵌入式实战
  • C++、汇编与易语言:三大编程语言深度对比
  • 探索OpenBoardView:硬件工程师的PCB分析利器