写在前面:压力只是暂时的,都会过去,这是我一周觉得听到的最顿悟的一句话了吧~javascript
1.引言php
js做为单线程的运行机制,一定有本身的运行顺序,在听了一次分享后,也好奇这种运行的机制究竟是什么?html
js可分为同步任务和异步任务,对于同步的任务,咱们固然知道按照顺序进行执行,可是对于异步的操做,会有一个优先级的执行顺序,分别为宏任务和微任务vue
宏任务(macrotasks)和微任务(microtasks)??包含什么?java
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering microtasks: process.nextTick, Promises, Object.observe(废弃), MutationObserver
在js执行时候,一个主线程里面都会有一个事件循环(消息循环|运行循环)和事件队列,存放各类要处理的事件信息,经过这个循环不断处理这些事件信息或消息。web
谈到这里,很明显知道,其实出现宏任务和微任务和浏览器以及js的执行机制有很大的关系。了解js的执行机制promise
2.javascript的执行runtime浏览器
这是一张javascript的执行机制图多线程
(1) javaScript Engine,Chrome 的引擎就是 V8异步
(2) Web APIs,DOM 的操做,AJAX,Timeout 等实际上调用的都是这里提供的
(3)Callback Queue,回调的队列,也就是刚刚全部的 Web APIs 里面的回调函数,实际上都是放在这里排队的
(4) EventLoop,事件循环,也就是刚所说的宏任务和微任务的容器
call Stack
自己就是一个调用栈(就像浏览器中的JavaScript解释器),追踪函数执行流的一种机制,当执行环境调用了多个函数时,经过调用栈,咱们能够追踪到哪个函数在执行,执行的函数体中又调用了哪些函数。
每调用一个函数,解释器就会把该函数添加进调用栈并开始执行。
正在调用栈中执行的函数还调用了其它函数,那么新函数也将会被添加进调用栈,一旦这个函数被调用,便会当即执行。
当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码。
当分配的调用栈空间被占满时,会引起“堆栈溢出”。
是存放执行的重要条件,也是由于只有一个调用栈,因此被称为单线程
callback quene
在js的编译阶段,将一些时间防止在执行队列中
EventLoop 事件循环
一个做用就是将callback quene队列里的执行事件放在在call stack中,执行
3.事件循环
js是单线程的,执行较长的js时候,页面会卡死,没法响应,可是全部的操做都会被记住到另外的队列。好比:点击了一个元素,不会马上的执行,可是等到js加载完毕后就会执行刚才点击的操做,可以知道有一个队列记录了全部有待执行的操做,这个队列分为微观和宏观。微观会比宏观执行得更快。
称为事件循环的缘由大多来源于源码
while (queue.waitForMessage()) { queue.processNextMessage(); }
能够看到入伏哦有消息就会执行,没消息就会继续等待
4.宏任务和微任务
是一种人们定义的执行名字,
如何区分宏任务和微任务呢?划分的标准是什么
console.log("开始执行1") console.log(Object.keys({a: 1})); setTimeout(() => { console.log(Object.keys({b: 2})); var promise = new Promise((resolve, reject) => { resolve(1); }); promise.then(res => { //后续增长测试 setTimeout(() => { console.log(Object.keys({e:1})) }, 0); console.log(Object.keys({c: 1})); }); }, 2000); console.log("结束执行2")
微观任务是在当前JS调用执行完了以后马上执行的,是同步的,在同一个调用栈里,没有多线程异步,如这里包括promise.then在内的setTimeout回调里的代码都是在DOMTimer.Fired执行的,只是说then被放到了当前要执行的整一个异步回调函数的最后面执行。因此setTimeout 0是给主线程的消息循环任务队列添加了一个新的task(回调),而promise.then是在当前task的V8里的microtask插入了一个任务。那么确定是当前正在执行的task执行完了才执行下一个task.vue的nextTick 也是一个微观任务
let img = new Image(); img.src = 'image01.png?_=' + Date.now(); img.onload = function () { console.log('img ready'); } console.log(Object.keys({e: 1}));