事件环EvenLoop相信大家应该不陌生,但是涉及的方面还挺多的,要掌握起来还是有一定难度,希望这篇总结能帮到你们~
我们先以一段代码作为示例
console.log('start');
setTimeout(() => {
console.log('timeout');
});
Promise.resolve().then(() => {
console.log('resolve');
});
console.log('end');
按照js将代码按顺序压入执行栈来说,结果应该为:
start
timeout
resolve
end
不不不!既然今天我们要讲的是EvenLoop事件环,我们就知道没这么简单了,我们看看最后执行的结果为:
start
end
resolve
timeout
不要慌,接下来让我们一起探个究竟:
等等…宏任务?同步? 感到陌生没关系,我们先放下这道题,待会再回头分许。接下来我们一起学习一些概念
我们知道js是单线程的,这意味着任务是一个接一个进行,可能遇到执行时间长的就会阻塞程序,效率太慢;这时就产生了异步任务,提高效率
异步一般是指 网络请求、计时器、DOM事件监听
什么是任务队列呢?
在js中所有任务分为宏任务和微任务
每次执行栈的代码就是一个宏任务,包括任务队列中的任务,每执行宏任务之前浏览器都会重新渲染页面。
为什么要有微任务?什么时候执行?
解决异步回调问题
类似银行业务办理,每个人排队等待办理自己的业务就是一个宏任务。当我办理好银行卡后,想临时增加一个 办理套餐业务(微任务),此时不会重新叫号再排一次队,而是继续办理完成后,才轮到下一个(宏任务)
总结一下:
有了前面知识的铺垫,我们对js执行有了一定了解,现在让我们总结一下
执行完宏任务时,要检查微任务队列,有则先执行,接着再执行浏览器UI线程的渲染工作
我们先回到最开始的题目
console.log('start');
setTimeout(() => {
console.log('timeout');
});
Promise.resolve().then(() => {
console.log('resolve');
});
console.log('end');
相信不难分析:
结果就很容易分析出来啦,不过这里要注意Promise本身属于同步代码,其promise.then才是异步操作
Promoise是为了解决回调地狱而产生,使用then方法链式编程。Promise意思是‘承诺’,可以当作一个容器,包含未来产生的结果,其结果有不同状态
新建一个Promose函数立即执行,因为Promise本身是同步的,其内部的then指定的回调函数才是异步,具体可以参考以下链接学习:
ES6中Promise学习
async表示该函数也是Promise异步函数,其await之前的代码也是立即执行,await后面的代码会执行,然后将结果放入任务队列中等待
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
应该不难得出结果如下:
script start
promise1
script end
promise2
setTimeout
关于浏览器事件环讲解到此结束,如有错漏,欢迎指正~