Node学习笔记(三)—— 阻塞、非阻塞与事件循环

阻塞代码

// 导入文件模块
let fs=require('fs')
// 读取input.txt 文件中数据
let data=fs.readFileSync('input.txt')
console.log(data.toString())  // 先执行
console.log("程序结束") // 后执行

非阻塞代码

let fs=require('fs')
fs.readFile('./input.txt',(err,data)=>{
    if(err) return console.log(err);
    console.log(data.toString()) // 后执行
})
console.log("程序结束") // 先执行

阻塞是按顺序执行的,而非阻塞是不需要按顺序的,如果需要处理回调函数的参数,我们就需要写在回调函数内

事件循环

  • Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

  • 在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

    // 导入events模块
    let events=require('events');
    // 定义eventEmitter对象
    let eventEmitter=new events.EventEmitter();
    // 创建链接连接成功时触发的函数
    let connectHandler=function connected(){
        console.log('链接成功') // 第一步执行
        // 链接成功后才触发数据接收事件
        eventEmitter.emit('data_received')
    }
    // 绑定触发链接时执行函数
    eventEmitter.on('connection',connectHandler)
    // 创建数据接收成功后触发的函数
    eventEmitter.on('data_received',()=>{
        console.log('数据接收成功') // 第二步执行
    })
    // 触发链接事件
    eventEmitter.emit('connection');
    console.log("程序执行完毕")  // 第三步执行
    

EventEmitter

  • events 模块只提供了一个对象: events.EventEmitterEventEmitter 的核心就是事件触发与事件监听器功能的封装。
  • EventEmitter 对象如果在实例化时发生错误,会触发 error 事件。当添加新的监听器时,newListener 事件会触发,当监听器被移除时,removeListener 事件被触发。
  • EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
方法
  1. addListener(event, listener),为指定事件添加一个监听器到监听器数组的尾部。

  2. on(event, listener),为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。

    server.on('connection', function (stream) {
      console.log('someone connected!');
    });
    
  3. once(event, listener),为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。

    server.once('connection', function (stream) {
      console.log('Ah, we have our first user!');
    });
    
  4. removeListener(event, listener),移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。它接受两个参数,第一个是事件名称,第二个是回调函数名称。

    var callback = function(stream) {
      console.log('someone connected!');
    };
    server.on('connection', callback);
    // ...
    server.removeListener('connection', callback);
    
  5. removeAllListeners([event]),移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。

  6. setMaxListeners(n)EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。

  7. listeners(event),返回指定事件的监听器数组。

  8. emit(event, [arg1], [arg2], [...]),按监听器的顺序执行执行每个监听器,如果事件有注册监听返回 true,否则返回 false

类方法
  • listenerCount(emitter, event),返回指定事件的监听器数量。

    events.emitter.listenerCount(eventName) //推荐
    
事件
  1. newListener,第一参数event - 字符串,事件名称,第二参数listener - 处理事件函数,该事件在添加新监听器时被触发。

  2. removeListener,第一参数event - 字符串,事件名称,第二参数listener - 处理事件函数,从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。

不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

实例
let events =require('events')
let eventEmitter=new events.EventEmitter()
let listener_first=function (){
    console.log("listener_first执行") // 第二步执行 || 第四步执行
}
let listener_second=function (){
    console.log("listener_second执行") // 第三步执行
}
eventEmitter.addListener('connection',listener_first)
eventEmitter.on('connection',listener_second)
let eventListeners=eventEmitter.listenerCount("connection")
console.log(eventListeners) // 第一步执行
eventEmitter.emit('connection')
eventEmitter.removeListener('connection',listener_second)
eventEmitter.emit('connection')
let eventListeners1=eventEmitter.listenerCount('connection')
console.log(eventListeners1) // 第五步执行
发布了122 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44876003/article/details/104783187