在写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
当函数执行的时候,按照函数内部的顺序依次执行,好比:若是此调用的函数是很耗时的,但它依然会等待调用函数的返回值,直到拿到预期的结果(即拿到了预期的返回值或者看到了预期的效果)为止才会执行后面的操做,那么这个函数就是同步的。markdown
//在函数返回时,得到了预期值,即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事件循环机制