大文件续传
回调函数
回调函数(callback function)是一种函数,它作为参数传递给另一个函数,并在某个特定时间点被调用。
回调函数是以函数作为参数传递并在调用者中执行的函数。它允许程序在异步任务完成时执行特定的操作。
语法
有名的回调函数语法
1 | function mainFun(callback){ |
匿名回调函数语法
1 | function mainFun(callback){ |
回调函数的参数
1 | function mainFun(callback){ |
应用
事件处理
事件处理 在浏览器环境中,事件处理器是回调函数的一个常见应用。例如,监听按钮的点击事件时,可以传入一个回调函数来定义当按钮被点击时要执行的逻辑。
1 | document.getElementById("mybutton").addEventListener('click',function(){ |
定时器
定时器 setTimeout 和 setInterval 是 JavaScript 中定时器的两个函数,它们都会接受一个回调函数。该回调函数会在指定的时间后执行。
1 | setTimeout(function(){ |
异步操作
异步操作(例如 AJAX 请求) 回调函数在处理异步操作时非常有用。通过回调函数,可以在服务器返回数据后进行处理,而无需阻塞代码的执行
1 | function fetchData(url,callback){ |
数组中的回调函数
数组方法中的回调 数组的 map、filter、reduce 等高阶函数都使用回调函数来对数组中的每个元素进行处理。
1 | let numbers = [1,2,3,4,5,6] |
回调地狱
当回调函数嵌套得过深时,代码会变得难以维护和阅读,这被称为回调地狱。
1 | function firstFunction(callback) { |
关于回调的困惑
一直以来我都觉得回调函数执行是有顺序的为什么说是异步操作。
回调函数的执行顺序确实会让人误以为它们是同步操作。但实际上,JavaScript 的回调函数在很多情况下是用于异步操作的,而这正是区分回调函数同步与异步执行的关键。
函数内部的回调执行是同步的:当我们在某个函数内部调用回调函数时,它是按照正常的函数调用顺序执行的。比如,当我们直接调用一个回调函数,它的执行过程和普通函数是一样的,是同步进行的。
回调函数在异步操作中显得是异步的:如果回调函数被用于处理异步操作(如定时器、网络请求、事件监听等),那么它的执行不会阻塞主线程,JavaScript 会先继续执行后面的代码。等到异步操作完成后,再执行回调函数,这种情况下回调函数相对于外面的代码是异步的。
异步执行的原因
JavaScript 是单线程的,这意味着它一次只能做一件事。但是,现代应用中有很多耗时的任务,比如:
- 读取文件
- 发送网络请求
- 数据库查询
- 定时操作(setTimeout 或 setInterval)
如果 JavaScript 是阻塞式的(即同步操作),它就无法同时处理多个任务。为了避免这种情况,JavaScript 引入了异步编程模型,通过回调函数、Promise 或 async/await 来处理那些需要较长时间完成的任务。
当异步操作执行时,JavaScript 引擎并不会阻塞主线程。相反,它会继续执行后续代码,直到异步操作完成。等到异步操作完成时,事件循环(event loop)将回调函数放入执行队列中,这时回调函数才会被执行。
事件循环(Event Loop)与回调函数
JavaScript 的事件循环是异步回调背后的核心机制。简单来说,JavaScript 的运行时环境由调用栈和任务队列组成:
- 调用栈:用来执行同步代码,函数按照调用顺序依次入栈和出栈。
- 任务队列:异步操作完成后,回调函数会被放入任务队列中等待执行。
当调用栈中的任务执行完毕(即同步代码全部完成),事件循环会从任务队列中取出回调函数,放到调用栈上执行。