NODE事件驱动

基本概念

  1. 事件: 事件是可以被 JavaScript 侦测到的行为,如onclick()。
  2. 事件驱动:只有当事件发生时候才会调用回调函数,这种函数执行的方式叫做事件驱动。
  3. 基于事件驱动的回调:通过事件驱动方式实现的回调叫做基于事件驱动的回调。如果和io有关就可以叫做基于异步回调的io。
  4. 事件循环:Event loop有大量的异步操作完成时需要调用相应回调函数,需要一种机制来管理执行先后,这种机制就叫做事件循环。node.js不断查询任务队列中是否有事件,查询到事件,调用相应javascript函数,机制为先进先出任务队列。

好处

  • 一个典型的事件驱动的程序,就是一个以线程形式存在的死循环,这个死循环包括两个部分,第一个部分是按照一定的条件接收并选择一个要处理的事件,第二个部分就是事件的处理过程。程序的执行过程就是选择事件和处理事件,而当没有任何事件触发时,程序会因查询事件队列失败而进入睡眠状态,从而释放cpu。

  • 事件驱动的程序,必定会直接或者间接拥有一个事件队列,用于存储未能及时处理的事件。

  • 事件驱动的程序可以按照一定的顺序处理队列中的事件,而这个顺序则是由事件的触发顺序决定的。

  • 事件驱动的程序能够让CPU 和内存在同一时间集中处理一件事,同时尽可能让耗时的 I/O 操作并行执行。对于低速连接攻击,Node.js 只是在事件队列中增加请求,等待操作系统的回应,因而不会有任何多线程开销,很大程度上可以提高 Web 应用的健壮性,防止恶意攻击。

相关事例

在基于线程的方式中(thread-based way)你到了柜台前,把你的点餐单给收银员或者给收银员直接点餐,然后等在那直到你要的食物准备好给你。收银员不能接待下一个人,除非你拿到食物离开。想接待更多的客户,容易!加更多的收银员!

当然,我们知道快餐店其实不是这样工作的。他们其实就是基于事件驱动方式,这样收银员更高效。只要你把点餐单给收银员,某个人已经开始准备你的食物,而同时收银员在进行收款,当你付完钱,你就站在一边而收银员已经开始接待下一个客户。在一些餐馆,甚至会给你一个号码,如果你的食物准备好了,就呼叫你的号码让你去柜台取。关键的一点是,你没有阻塞下一个客户的订餐请求。你订餐的食物做好的事件会导致某个人做某个动作(某个服务员喊你的订单号码,你听到你的号码被喊到去取食物),在编程领域,我们称这个为回调(callback function)。

基本思路

NODE事件驱动

  1. 当有请求发生时,node.js将这些请求放到队列中,此时不占CPU只占内存队列
  2. 事件循环从队列中解析这些请求,如果存在回调函数,判断是否存在阻塞,存在的话事件循环从线程池中检索一个线程,否则,直接执行回调。回调函数主要执行的操作是:1.发送一个响应 2.安排另一个事件 3.结束程序。
  3. 当程序执行到回调函数时,浏览器运行回调函数。

    类比于点餐事件。当A点餐时,点餐系统会生成A的订单放入订单队列中,B点餐原理同上。后厨(事件循环)会根据订单制作相应的食物。如果只有一个厨师,而订单很多,厨师一般会将订单放在一起(线程池)查看有无相同的食物。当前台进行催单时,厨师会优先制作催单的食物(这相当于是当程序运行到指定的行时会优先执行相应的回调函数)。