【知识点】JS运行机制

为何js是单线程的

咱们用反证法证实这个问题,假设js是多线程的。es6

场景描述:promise

假设如今有2个进程:process1,process2。因为是js是多进程的,因此这两个进程同时对一个dom进行操做。浏览器

process1 删除了该dom。bash

process2 编辑了该dom。多线程

同时下达2个矛盾的命令,浏览器究竟该如何执行呢?dom

显然做为浏览器脚本语言,就决定了js只能是单线程的,也称为主线程。异步

JS为何须要异步

一样用反证法,假设js是同步的。oop

场景描述:ui

若是JS中不存在异步,只能自上而下执行,若是上一行解析时间很长,那么下面的代码就会被阻塞。spa

对于用户而言,阻塞就意味着"卡死",这样就致使了不好的用户体验。

JS单线程又是如何实现异步的呢?

经过的事件循环(event loop)实现异步。

什么是事件循环

js任务分类:

  • macro-task(宏任务):包括总体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise.then(),MutationObserver。

event loop:

  1. 执行一个宏任务,过程当中若是遇到微任务,就将其放到微任务的【事件队列】里
  2. 当前宏任务执行完成后,会查看微任务的【事件队列】
  3. 若是有微任务,将里面所有的微任务依次执行完
  4. 若是没有微任务,跳到第1步。

event loop图解

总结:

涉及概念: 运行栈(同步任务)、任务队列(异步任务)、event loop

不断去任务队列中取异步任务的过程叫event loop

何时会开启异步任务:setTimeout 和 setIntveral、DOM事件、es6中的promise等

语句放入异步任务队列时机:遇到异步任务不会马上把代码放到任务队列中,会等到触发时(settimeout 时间到了 dom事件触发了)在放到任务队列中:

var a= 1;
setTimeout(a, 1000);
setTimeout(b, 500);
//b先被放到异步队列
复制代码

例子

例子1

// 1 3 2
console.log(1);      //同步任务
setTimeout(function(){      //异步任务
	console.log(2);
},0)
console.log(3);      //同步任务
复制代码

例子2

// 1
console.log(1);      //同步任务
while(true){      //同步任务
			
}
console.log(2);      //同步任务
复制代码

例子3

// 1
console.log(1);      //同步任务
setTimeout(function(){      //异步任务
	console.log(2);
},0)
while(true){      //同步任务
			
}
复制代码

例子4

//4 4 4 4
for(var i=0;i<4;i++){            //同步任务
	setTimeout(function(){      //异步任务
		console.log(i);
	},1000)
}
复制代码

例子5

//2 4 3 1
setTimeout(function(){
    console.log('1')
});
 
new Promise(function(resolve){
    console.log('2');
            resolve();
}).then(function(){
    console.log('3')
});
 
console.log('4');
复制代码
相关文章
相关标签/搜索