22

回调定义

刚开始学习javascript时,对回调函数的理解仅仅停留在知道定义阶段。什么是回调函数? 就是将一个函数作为参数传递给另一个函数,作为参数的这个函数就是回调函数。 至于为什么要用到回调函数?回调函数有什么作用? 当时对这些一无所知! 最近学习node.js涉及到了大量的异步编程,很多地方都需要用到回调函数,所以这两天深入了解了JavaScript的回调函数,下面是我对回调函数的理解。

函数也是对象

想要弄明白js回调函数,首先要清楚函数的规则,在javascript中函数是一个对象,准确的来说函数是用function()构造函数创建的一个function对象,因此我们可以将函数存储在变量中,当然也就可以将存储在变量中的函数作为一个参数传递给另一个函数,这就是回调函数。
举个例子:

var callback = function(arg3) {
    console.log('callback Totle is:' + arg3)
  }

function fn(arg1, arg2, cb) {
  var Total = arg1 + arg2;
  cb(Total);
  console.log('mainFunction Totle is:' + Total)
}

fn(2, 2, callback)   // 调用fn()函数,并传入2, 2, callback作为参数

上面例子中我们将一个匿名函数赋值给变量callback,同时将callback作为参数传递给了fn()函数,这时在函数fn()中callback就是回调函数。

同步回调和异步回调

上面的代码执行结果为:

callback Totle is:4
mainFunction Totle is:4

不对啊! 回调函数不是应该在主函数的最后执行吗?
对,很多介绍回调函数的例子讲到这里是就完了,异步回调函数的确是应该在函数的最后执行,不过上面的例子是一个同步回调函数,函数的执行顺序依然自上而下顺序执行。 那么什么是异步回调呢? 我们又怎么实现异步回调呢? 下面我们举两个例子来说明:

示例1:

function f2() {

    console.log('f2 finished') 
}

function f1(cb) {

    setTimeout(cb,1000)        //用setTimeout()模拟耗时操作
    console.log('f1 finished')
}

f1(f2);    //得到的结果是 f1 finished ,f2 finished

这里我们用setTimeout()来模拟耗时操作的前提是js中的setTimeout()函数支持异步处理,所以我们得到的结果是 f1 finished ,f2 finished

示例2:

var fs = require("fs");

fs.readFile('input.txt','utf-8', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});

console.log("程序执行结束!");

程序执行的结果是:

$ node app
程序执行结束!
我们来测试一下异步回调函数

上面例子中我们先创建了一个文件input.txt,里面的内容是:'我们来测试一下异步回调函数'
如果按照同步的思维,程序应该执行fs.readFile,直到文件读完之后才执行后面的console.log("程序执行结束!"); 然而node中的fs.readFile是支持异步处理的,因此程序执行到这儿的时候并不会阻塞,而是继续向后执行,当文件读取完毕之后再自动调用传入的匿名回调函数,因此出现了上面的结果。

参考文章:
详解回调函数——以JS为例解读异步、回调和EventLoop http://blog.csdn.net/tywinsta...
Javascript异步编程的4种方法 - 阮一峰的网络日志http://www.ruanyifeng.com/blo...


dayday_up
344 声望15 粉丝

韬光养晦,厚积薄发