浅谈,JavaScript 运行机制和Event Loop
JavaScript是一个非常灵活的语言且是单线程所谓是单线程就好比你去一个银行,银行只开设了一个窗口,然而一个窗口就好比一个线程,取钱的人就好比JS代码。也就是说
javascript是按照语句出现的顺序执行的
其实这样说是很严谨,例如:
setTimeout(
function(){
console.log('定时器开始啦')
});
new Promise(
function(resolve){
console.log('马上执行for循环啦');
for(var i = 0; i < 100; i++)
{
i == 99 && resolve(); }
}).then(
function(){
console.log('执行then函数啦')
});
console.log('代码执行结束');
你觉得会是一行一行的执行吗?为什么会出现我们不一样的结果呢,一行一行的执行对我们执行效果很不好那么怎么解决呢?这就涉及到JS 中的
同步任务
异步任务
何为同步呢?简单的理解就是你向一个女孩子表白,你打电话给她,说喜欢她。这个过程你一直不挂电话,啥事也不干就等她回答,对于你来说就是同步。比如页面骨架和页面元素的渲染就是同步,而异步呢,我进常用AJAX请求。下面一张图让我们来体会一下:
那么这张图说明了什么呢?我们看看
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
当指定的事情完成时,Event Table会将这个函数移入Event Queue。
主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
上述过程会不断重复,也就是常说的Event Loop(事件循环)。
我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
那我们来看一下代码吧,加深理解。
var data={}
$.ajax(
{
url:xxxxxx,
data:data,
success:() => {
console.log('发送成功!');
}
})
console.log('代码执行结束');
有人这么平淡无奇的AJAX有啥奇怪,不妨我来看看这段代码的含义,
ajax进入Event Table,注册回调函数success。
执行console.log('代码执行结束')。
ajax事件完成,回调函数success进入Event Queue。
主线程从Event Queue读取回调函数success并执行。
有的同学就觉得我明白了,下面我再来一段代码看看,
console.log('main1');
process.nextTick(function() {
console.log('process.nextTick1');
});
setTimeout(function() {
console.log('setTimeout');
process.nextTick(function() {
console.log('process.nextTick2');
});
}, 0);
new Promise(function(resolve, reject) {
console.log('promise');
resolve();
}).then(function() {
console.log('promise then');
});
console.log('main2');
不妨我们来分析下:
开始执行全局SCRIPT宏任务,输出 main1,process.nextTick 放入tickTaskQueen,setTimeout放入 macroTaskQueen, new Promise 执行 输出 promise,then 方法 放入 MicroTaskQueen , 接着 最后一行代码 console.log 输出 main2
当前的 宏任务执行完毕,开始清空微任务,先清空tickTaskQueen ,执行 console.log('process.nextTick1'); 输出'process.nextTick1;再清空MicroTaskQueen执行 console.log('promise then'); 输出promise then;微任务全部清空。
开始下次 eventLoop; 执行 setTimeout; 第一行 console.log('setTimeout'); 输出setTimeout; process.nextTick 将任务放入了tickTaskQueen;当前宏任务执行完毕;开始清空MicroTaskQueen,清空tickTaskQueen ,执行 console.log('process.nextTick2');输出process.nextTick2;
顺便附上图:
这幅图很好说明时间循环的机制吧,好了这次就到这里,欢迎大家提意见。