回调函数
定义
什么是回调函数呢?
通俗的讲,将一个函数A作为参数传递给函数B,在函数B内对函数A进行调用,函数A就是回调函数。
Node.js 异步编程的直接体现就是回调。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
理解
(1)异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。
例1:
function main(info,callback){
console.log('回家发短信')
callback(info) //调用回调函数
}
function sendMsg(msg){
console.log(msg)
}
main('我回家了',sendMsg) //调用主函数
//回家发短信
//我回家了
//执行结果还是同步的
(2)在非阻塞的I/O操作中,主程序的执行和回调函数不是同步,实现异步。
例2:
const fs = require('fs');
//异步读取文件 的内容(回调函数)
fs.readFile('demo.txt',function (err,data){
if(err){
console.log(err); //输出错误信息
}
console.log(data.toString()); //输出文件内容
})
//3、主程序流程结束
console.log("node程序已经执行结束")
//node程序已经执行结束
//文件内容
我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。
事件处理机制
Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
1、首先,会形成一个事件处理的队列,用于将所有的事件请求放到队列中(例如读写文件等操作请求);
2、然后启动事件循环机制,对事件队列里面的事件进行不断的轮询检查,如果有需要处理的事件,就对每个事件依次进行处理;
3、进行事件监听:
(1)引入事件模块:events
(2)创建事件监听对象:EventEmitter
(3)注册监听:监听不同类型的事件(使用on函数)
4、对事件进行触发,使用emit函数。
Node.js 使用事件驱动模型,当web server(web服务器)接收到请求,就把请求连接关闭,然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户,服务器不断接收用户的请求,任务队列不断给用户响应结果,这个请求响应的过程实际上还是一个异步的过程。
由于nodejs是单线程运行的,所以nodejs需要借助事件轮询,不断去查询事件队列中的事件消息,然后执行该事件对应的回调函数。
这个模型非常高效可扩展性非常强,因为 web server 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)
补充
事件监听的各种方法:
-
addListener(event,listener)
:事件监听函数
-
on(event, listener)
:对指定对象绑定事件处理函数(addListener方法的别名)
-
once(event, listener)
:对指定对象指定只执行一次的事件处理函数
-
removeListener(event, listener)
:删除事件
-
setMaxListeners(n)
:指定对象处理函数的最大数量,n为正数值,代表最大的可指定事件处理函数的数量
-
listeners(event)
:获取指定对象的所有事件处理函数
-
emit(event, [arg1], [arg2], [...])
:手动触发指定事件