07node_浏览器事件循环和node事件循环

什么是事件循环?

事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁

进程和线程

线程和进程是操作系统中的两个概念:

进程(process):计算机已经运行的程序;

线程(thread):操作系统能够运行运算调度的最小单位;

操作系统类似于一个工厂;

工厂中里有很多车间,这个车间就是进程;

每个车间可能有一个以上的工人在工厂,这个工人就是线程

浏览器和JavaScript

我们经常会说JavaScript是单线程的,但是JavaScript的线程应该有自己的容器进程:浏览器或者Node。

目前多数的浏览器其实都是多进程的,当我们打开一个tab页面时就会开启一个新的进程,这是为了防止一个页面卡死而造成所有页面无法响应,整个浏览器需要强制退出;

每个进程中又有很多的线程,其中包括执行JavaScript代码的线程;

但是JavaScript的代码执行是在一个单独的线程中执行的:

这就意味着JavaScript的代码,在同一个时刻只能做一件事;如果这件事是非常耗时的,就意味着当前的线程就会被阻塞

浏览器的事件循环

1,先执行初始化代码,将回调函数给对应模块

2,当事件发生后,管理模块将回调函数放入对应队列(宏队列,微队列)

3,初始化代码执行完后,依次读取队列里回调函数(队列读取顺序如下)

async,await 

也就是说await后的代码,看作初始化代码,立即执行

await下一句,加入微任务队列


node事件循环

和浏览器差不多,分的更详细罢了,也分微宏任务队列,

顺序:初始化代码(main script)  -> nextTicks()  ->  其他微任务(promise.then)  -> times(定时器等,不包括立即执行函数) -> IO -> 立即执行函数     ->close等

浏览器中的EventLoop是根据HTML5定义的规范来实现的,不同的浏览器可能会有不同的实现,而Node中是由libuv实现的

事件循环像是一个桥梁,是连接着应用程序的JavaScript和系统调用之间的通道:

无论是我们的文件IO、数据库、网络IO、定时器、子进程,在完成对应的操作后,都会将对应的结果和回调函数放到事件循环(任务队列)中;事件循环会不断的从任务队列中取出对应的事件(回调函数)来执行

一次完整的事件循环Tick分成很多个阶段:

定时器(Timers):本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。

待定回调(Pending Callback):对某些系统操作(如TCP错误类型)执行回调,比如TCP连接时接收ECONNREFUSED。

idle, prepare:仅系统内部使用。

轮询(Poll):检索新的 I/O 事件;执行与 I/O 相关的回调;

检测:setImmediate() 回调函数在这里执行。

关闭的回调函数:一些关闭的回调函数,如:socket.on('close', ...)

面试题解析

大概率是settimeout  setimmediate

因为虽然settimeout是延时0秒,但它实际上是主线程执行完后立即执行它,会有延时

当初始化事件循环时间较短,而延时较高时,settimeout还没加入队列,就先执行立即执行函数了

阻塞IO与非阻塞IO

你可能感兴趣的:(07node_浏览器事件循环和node事件循环)