在写js代码的时候咱们每每都但愿js代码的执行顺序是按照本身所想那样执行,但结果总事与愿违。因此今天就想花时间搞懂js的事件执行机制究竟是什么样的。javascript
js中事件分为宏任务和微任务两类,任务又分为同步任务和异步任务。他们之间的执行顺序将依次进行说明html
js中事件分为两类java
那么等到何时才能执行呢?就是等到主线程的任务执行完毕为空的时候。那咱们怎么知道何时主线程为空呢?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。 用流程图来归纳上述步骤:node
let data = [];
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('发送成功!');
}
})
console.log('代码执行结束');
复制代码
js中任务分为两类ajax
用流程图表示上述流程:promise
setTimeout(function() {
console.log('setTimeout');
},1000)
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
复制代码
如今看一个比较复杂的例子浏览器
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
输出:
1
2
4
3
5
复制代码
你们都知道js是是一门单线程语言,因此他的语句确定是一句一句执行的。可是js中又存在同步操做和异步操做,那么就会有疑问,js是如何经过单线程的方式来实现异步操做的呢?bash
当函数执行的时候,按照函数内部的顺序依次执行,好比:若是此调用的函数是很耗时的,但它依然会等待调用函数的返回值,直到拿到预期的结果(即拿到了预期的返回值或者看到了预期的效果)为止才会执行后面的操做,那么这个函数就是同步的。网络
//在函数返回时,得到了预期值,即2的平方根
Math.sqrt(2);
//在函数返回时,得到了预期的效果,即在控制台上打印了'hello'
console.log('hello');
复制代码
若是函数是异步的,发出调用以后,立刻返回,可是不会立刻返回预期结果。调用者没必要主动等待,当被调用者获得结果以后会经过回调函数主动通知调用者。多线程
//读取文件
fs.readFile('hello.txt', 'utf8', function(err, data) {
console.log(data);
});
//网络请求
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = xxx; // 添加回调函数
xhr.open('GET', url);
xhr.send(); // 发起函数
复制代码
上述示例中读取文件函数 readFile和网络请求的发起函数 send都将执行耗时操做,虽然函数会当即返回,可是不能马上获取预期的结果,由于耗时操做交给其余线程执行,暂时获取不到预期结果(后面介绍)。而在JavaScript中经过回调函数 function(err, data) { console.log(data); }和 onreadystatechange ,在耗时操做执行完成后把相应的结果信息传递给回调函数,通知执行JavaScript代码的线程执行回调。
前面说到js是一门单线程语言,他是怎么实现异步操做的呢。JS的运行一般是在浏览器中进行的,具体由JS引擎去解析和运行。下面咱们来具体了解一下浏览器。 浏览器的内核是多线程的。 一个浏览器一般由如下几个常驻的线程:
须要注意的是,渲染线程和JS引擎线程是不能同时进行的。 渲染线程在执行任务的时候,JS引擎线程会被挂起。由于JS能够操做DOM,若在渲染中JS处理了DOM,浏览器可能就不知所措了。
JS引擎能够说是JS虚拟机,负责JS代码的解析和执行。之因此说JavaScript是单线程,就是由于浏览器在运行时只开启了一个JS引擎线程来解析和执行JS。那为何只有一个引擎呢?若是同时有两个线程去操做DOM,浏览器是否是又要不知所措了。 因此,虽然JavaScript是单线程的,但是浏览器内部不是单线程的。一些I/O操做、定时器的计时和事件监听(click, keydown...)等都是由浏览器提供的其余线程来完成的。也就是以前说的Event Queue。
JavaScript异步机制详解
这一次,完全弄懂 JavaScript 执行机制
简单总结下JS中EventLoop事件循环机制