- 一、线程和进程
- 1、单线程和多线程
- 2、GUI渲染线程
- 3、JS引擎线程
- 4、同步任务和异步任务
- 二、入栈和出栈
- 三、例子与解析
- setInterval和setTimeout
console.log('1');
setTimeout(function(){console.log('2');
},0);
setTimeout(function(){console.log('3');
},2000);
console.log('4');
一、线程和进程
在解释JavaScript事件循环机制之前我们先了解线程和进程。
进程 是CPU资源分配的最小单位
线程 是CPU调度的最小单位
1、单线程和多线程
C、C++、JAVA支持多线程
JavaScript是单线程(最终操作页面的dom结构,以防两个JS同时操作页面的同一个dom节点而造成混乱)
浏览器是多线程(每个tab页为对应一个进程,多个空白页则进程合并为一)
2、GUI渲染线程
主要负责页面的渲染,解析HTML、CSS,构建DOM树,布局和绘制等。
当界面需要重绘或者由于某种操作引发回流时,将执行该线程。
该线程与JS引擎线程互斥,当执行JS引擎线程时,GUI渲染会被挂起,当任务队列空闲时,JS引擎才会去执行GUI渲染。
3、JS引擎线程
该线程当然是主要负责处理 JavaScript脚本,执行代码。
也是主要负责执行准备好待执行的事件,即定时器计数结束,或者异步请求成功并正确返回时,将依次进入任务队列,等待 JS引擎线程的执行。
该线程与 GUI渲染线程互斥,当 JS引擎线程执行 JavaScript脚本时间过长,将导致页面渲染的阻塞。
4、同步任务和异步任务
同步任务:可以立即执行的任务。
Console.log()、new Promise、var、±*/;
异步任务:不立即执行
- 宏任务
任务队列可多个(script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering) - 微任务
任务队列只有一个 (process.nextTick, Promise的then(), MutationObserver)
二、入栈和出栈
栈 就像是一个容器,任务都是在栈中执行。
主线程 就像是操作员,负责执行栈中的任务。
任务队列 就像是等待被加工的物品。
异步任务完成注册后会将回调函数加入任务队列等待主线程执行。
执行栈中的同步任务执行完毕后,会查看并读取任务队列中的事件函数,于是任务队列的函数结束等待状态,进入执行栈,开始执行。
三、例子与解析
console.log(1);
function fn1 (){console.log(2);
}
function fn2 (){console.log(3);fn1();
}
setTimeout (function(){console.log(4);
},2000);
fn2();
console.log(5);
流程图如下:
(注:W3C在 HTML标准中规定,规定要求 setTimeout中低于 4ms的时间间隔算为 4ms)
四、setInterval和setTimeout
当使用setInterval来进行页面实时刷新数据(ajax请求)时, setInterval会不断消耗网页内存,如果不清理会一直消耗直到网页卡死。
解决方法一:保证setInterval对象只创建一次
var status = true;
Var time = function (param) {
$.ajax({ success: function (returnValue) { if (status) {status= false; window.setInterval(" time()", 5000); }} });