回调函数
什么是回调呢?比如我们在编写 JavaScript 脚本时,不知道用户何时点击按钮,因此通常会为按钮的点击事件定义一个事件处理程序,该事件处理程序会接收一个函数,用来在点击事件被触发时调用,这就是所谓的回调。
因此,回调本质上是一个函数,它可以作为值传递给另一个函数,并且只有在特定事件发生时才会被执行。例如,下面代码给按钮的点击事件绑定一个回调函数:
document.getElementById('button').addEventListener('click', () => {
… //被点击
})
Node.js 异步编程的直接体现就是回调函数,Node.js 中使用了大量的回调函数,Node.js 中的大部分 API 都支持回调函数,如第 7 章中讲解过的操作文件的方法,基本上都同时提供了同步和异步操作的方法,并且默认使用的都是异步操作,在异步操作方法中都需要传递一个 callback
回调函数。
【例9.1】回调函数的简单应用。(实例位置:资源包\源码\09\01)
在 WebStorm
中创建一个 .js
文件,其中定义两个函数 fooA
和 fooB
,然后将 fooA
函数作为参数传递给 fooB
,以执行相应的加法运算,代码如下:
function fooA() {
return 1
}
function fooB(a) {
return 2 + a
}
//fooA是一个函数,但这里作为一个参数在fooB函数中被调用
c = fooB(fooA())
console.log(c)
运行程序,结果如图9.5所示。

接下来,通过一个实例讲解如何通过异步编程调用回调函数。
【例9.2】异步调用回调函数。(实例位置:资源包\源码\09\02)
在 WebStorm
中创建一个 .js
文件,该文件中主要实现将一个全局变量 a 从初始值 0 在 3 秒后变为 6 的过程,代码如下:
var a = 0;
function fooA(x) {
console.log(x)
}
function timer(time) {
setTimeout(function () {
a=6
}, time);
}
console.log(a);
timer(3000);
fooA(a);
运行程序,效果如图9.6所示。
通过观察图9.6可以发现,程序并没有按照我们的设想执行,这是因为虽然 timer
函数中将变量 a
设置为 6,但是程序执行时,由于 timer
函数中使用了 setTimeout
,其不会阻塞后面代码的执行,因此程序并不会等待 timer
函数执行完,而是直接执行了最后一行的 fooA
函数,而此时还没有经过 3 秒的时间,所以 a 的值仍是 0。

如果想达到我们希望的效果,应该在 timer
函数中加入一个回调函数作为参数,然后调用时,将 fooA
函数作为参数传递给 timer
函数,即代码修改如下:
var a = 0
function fooA(x) {
console.log(x)
}
function timer(time, callback) {
setTimeout(function () {
a = 6
callback(a); //使用回调函数执行输出操作
}, time);
}
console.log(a)
timer(3000,fooA)
再次运行程序,结果如图9.7所示。
