前端浏览器Event loop是个什么鬼!

502 阅读4分钟

进程 与 线程

进程是操作系统分配资源和调度任务的基本单位
线程是建立在进程上的一次程序运行单位
一个进程上可以有多个线程

多进程的浏览器

1) 用户界面-包括地址栏、前进/后退按钮、书签菜单等
2) 浏览器引擎-在用户界面和呈现引擎之间传送指令(浏览器的主进程)
3) 渲染引擎,也被称为浏览器内核(浏览器渲染进程)
4) 一个插件对应一个进程(第三方插件进程)
5) GPU提高网页浏览的体验(GPU进程)

渲染引擎

渲染引擎内部是多线程的,包含: ui线程 js线程 且两者是互斥的
    因为JS运行结果会影响到ui线程的结果;
    ui更新会被保存在队列中等到js线程空闲时立即被执行。

js单线程(主线程)

javascript在最初设计时设计成了单线程,为什么不是多线程呢?
    如果多个线程同时操作DOM那岂不会很混乱?
    这里所谓的单线程指的是主线程是单线程的,所以在Node中主线程依旧是单线程的。

其他线程

1) 浏览器事件触发线程(用来控制事件循环,存放setTimeout、浏览器事件、ajax的回调函数)
2) 定时触发器线程(setTimeout定时器所在线程)
3) 异步HTTP请求线程(ajax请求线程)

浏览器中的Event Loop (事件循环)

1) 1.所有同步任务都在主线程上执行,形成一个执行栈
2) 主线程之外,还存在一个任务队列。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
3) 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,将队列中的事件放到执行栈中依次执行
4) 主线程从任务队列中读取事件,这个过程是循环不断的

Node系统

1) 我们写的js代码会交给v8引擎进行处理
2) 代码中可能会调用nodeApi,node会交给libuv库处理
3) libuv通过阻塞i/o和多线程实现了异步io
4) 通过事件驱动的方式,将结果放到事件队列中,最终交给我们的应用。

同步与异步

同步和异步关注的是消息通知机制

1) 同步就是发出调用后,没有得到结果之前,该调用不返回,一旦调用返回,就得到返回值了。 简而言之就是调用者主动等待这个调用的结果
2) 而异步则相反,调用者在发出调用后这个调用就直接返回了,所以没有返回结果。换句话说当一个异步过程调用发出后,调用者不会立刻得到结果,而是调用发出后,被调用者通过状态、通知或回调函数处理这个调用。

阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

1) 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
2) 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

组合

同步异步取决于被调用者,阻塞非阻塞取决于调用者

1) 同步阻塞
2) 异步阻塞
3) 同步非阻塞
4) 异步非阻塞

宏任务和微任务

任务可分为宏任务和微任务

1) macro-task(宏任务): setTimeout, setInterval, setImmediate, I/O MessageChannel
2) micro-task(微任务): process.nextTick, 
    原生Promise(有些实现的promise将then方法放到了宏任务中);
    Object.observe(已废弃), MutationObserver

什么场合下应该考虑使用Node框架

当应用程序需要处理大量并发的I/O操作,而在向客户端响应之前,应用程序并不需要进行非常复杂的处理。

1) 聊天服务器
2) 电子商务网站