您的位置:首页 > Web前端 > JavaScript

javaScript运行机制及Event Loop

2017-11-11 19:23 288 查看

js时单线程语言

因为js的主要用途是【与用户互动以及操作DOM】,故js只能是单线程。

为了利用多核CPU的计算能力,H5提出Web Worker标准,允许js脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。

任务队列

单线程,意味着要有【任务队列】(task queue)

所有【任务】分为两种:

【同步任务】(在【主线程】上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务)

【异步任务】(不进入主线程,而进入任务队列的任务)

异步执行的运行机制

所有同步任务都在主线程上执行,形成一个【执行栈】;

主线程之外,还存在一个【任务队列】。只要异步任务有了运行结果,就在任务队列中放置一个事件;

一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列中的事件,与之对应的异步任务就结束等待状态,进入执行栈,开始执行;

主线程不断重复第三步;

【小结】:

js的运行机制:只要主线程空了,就回去读取任务队列。

事件和回调函数

任务队列是一个事件的队列,即消息队列。IO设备完成一项任务,就在任务队列中添加一个事件,表示相关的异步任务可以进入执行栈了。主线程读取任务队列中的事件。

任务队列中的事件:IO设备事件,用户操作产生的事件。

【回调函数】:会被主程序挂起的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

【任务队列】:先进先出。

Event Loop



主线程运行时,产生【堆】和【栈】,栈中的代码调用各种【外部API】,它们在【任务队列】中加入【事件】。只要栈中的代码执行完毕,主线程就回去读取任务队列,依次执行哪些事件所对应的【回调函数】。

执行栈中的代码【同步任务】,总是在读取任务队列【异步任务】之前执行。

定时器

任务队列中可放:异步任务的事件、定时事件

【定时器功能】:定时执行的代码,
setTimeout
setTimeInterval


setTimeout(fn, t)
的含义是:指定某个任务在主线程最早可得的空闲时间执行,尽可能早地执行。它在任务队列的尾部添加一个事件,因此要等到同步任务和任务队列现有的事件都处理完,才会得到执行。

HTML5规定了
setTimeout
的time参数的最小值,若低于4毫秒,就会自动增加。另外,对于DOM的变动通常不会立即执行,而是每16毫秒执行一次。

setTimeout()
只是将事件插入了任务对垒,必须等到当前代码执行栈执行完,主线程才会去执行它指定的回调函数。若当前
4000
代码耗时很长可能要等很久,所以并不能保证回调函数一定会在setTimeout()指定的时间执行。

Nodejs环境下

执行过程:

V8引擎解析js脚本

解析后的代码,调用Node API

libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(【事件循环】),以异步的方式将任务的执行结果返回给V8引擎

V8引擎再将结果返回给用户

(未完待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: