javascript从诞生之日起就是一门  单线程的  非阻塞的  脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event loop(事件循环),本文就讲解下事件循环。

event loop它最主要是分三部分:主线程、宏队列(macrotask)、微队列(microtask)

js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在macrotask或者microtask里面

主线程

就是访问到的script标签里面包含的内容,或者是直接访问某一个js文件的时候,里面的可以在当前作用域直接执行的所有内容(执行的方法,new出来的对象等

宏队列(macrotask)

setTimeout、setInterval、setImmediate、I/O、UI rendering

微队列(microtask)

promise.then、process.nextTick

执行顺序

1、先执行主线程

2、遇到宏队列(macrotask)放到宏队列(macrotask)

3、遇到微队列(microtask)放到微队列(microtask)

4、主线程执行完毕

5、执行微队列(microtask),微队列(microtask)执行完毕

6、执行一次宏队列(macrotask)中的一个任务,执行完毕

7、执行微队列(microtask),执行完毕

8、依次循环。。。

看下面代码练习练习

console.log(1)
process.nextTick(() => {
console.log(8)
setTimeout(() => {
console.log(9)
})
})
setTimeout(() => {
console.log(2)
new Promise(() => {
console.log(11)
})
})
requestIdleCallback(() => {
console.log(7)
})
// 特殊说明: new Promise()属于主线程任务
let promise = new Promise((resolve,reject) => {
setTimeout(() => {
console.log(10)
})
resolve()
// 这个console也属于主线程任务
console.log(4)
})
fn()
console.log(3)
promise.then(() => {
console.log(12)
})
function fn(){
console.log(6)
}

结果是1、4、6、3、12、8、2、11、10、9、7

这个写法可以囊括80%以上的event loop循环机制的场景了,下面开始梳理具体的运行机制。

js是从上到下执行的,所以上来先打印的是 1 ,继续往下走;

遇见了process.nextTick,因为它属于微队列(microtask),并且当前主线程的代码还没有执行完毕,所以它被展示扔到了微队列里,暂时不打印;

这个时候又遇到了setTimeout,setTimeout是属于宏队列(macrotask);

requestIdleCallback,这里也是不立即执行的,它也不属于任何队列,这里不做详细解释;

promise在实例化的时候,这里的setTimeout继续被丢到了宏队列(macrotask)中,并执行了成功的方法,在有promise.then的调用的时候就会去出发,但这里不做打印,接着发现了console,这里直接打印 4 );

fn函数直接调用,直接打印 6

console,直接打印 3

promise.then因为它属于微队列,但是它在promise实例化的时候被调用了,所以它会在微队列的最前面执行;

到这里主线程里面就没有任何可以执行到东西了,下面开始走微队列(microtask):

由于promise.then被提前调用了,所以它会先执行,打印 12

微队列(microtask)里面还有一个,就是上面的process.nextTick,执行它,打印 8 ,这个时候发现它有一个setTimeout,放到宏队列(macrotask);

到这里微队列就走完了,下面开始走宏队列(macrotask):

最外面的setTimeout在一开始的时候被放了进去,所以先执行它,打印 2 ,发现它里面有promise被实例化,直接执行,打印 11

下一个要走的就是promise里面的setTimeout,打印 10

还剩最后一个setTimeout,就是process.nextTick里面的,打印 9

到这里主线程、宏队列(macrotask)、微队列(microtask)就全都跑完了,在全部跑完的时候,requestIdleCallback才会执行,打印 7

requesIdleCallback会在当前浏览器空闲时期去依次执行,在整个过程当中你可能添加了多个requestIdleCallback,但是都不会执行,只会在空闲时期,去依次根据调用的顺序就执行。

js事件循环机制(Event Loop)的更多相关文章

  1. Node.js 事件循环(Event Loop)介绍

    Node.js 事件循环(Event Loop)介绍 JavaScript是一种单线程运行但又绝不会阻塞的语言,其实现非阻塞的关键是“事件循环”和“回调机制”.Node.js在JavaScript的基 ...

  2. 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)

    JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...

  3. js高级-浏览器事件循环机制Event Loop

    JavaScript 是队列的形式一个个执行的 同一时间只能执行一段代码,单线程的  (队列的数据结构) 浏览器是多线程的 JavaScript执行线程负责执行js代码 UI线程负责UI展示的 Jav ...

  4. 理解js事件循环(event loop)

    队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...

  5. 初探nodejs事件循环机制event loop

    nodejs的特点 nodejs 具有事件驱动和非阻塞I/O的特点. 事件驱动是指nodejs把每一个任务当成事件来处理. 非阻塞I/O是指nodejs遇到I/O任务时,会从线程池调度单独的线程处理I ...

  6. js事件循环(event loop)

    我们都知道,js是单线程的,虽然现在有 worker 的存在,但是也只是可以进行运算,并不能操作 dom: js最一开始执行的线程,是主线程,然后主线程执行完毕后,是微队列 microtask 的循环 ...

  7. 关于事件循环机制event loop

    setTimeout(()=> { console.log('settimeout') },100) console.log('开始') console.log('结束') new Promis ...

  8. 深入理解JavaScript的事件循环(Event Loop)

    一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) ...

  9. js事件循环机制辨析

     对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的 ...

随机推荐

  1. Hibernate开发环境搭建

    一.下载Hibernate包的下载 官网地址:http://hibernate.org/orm/ 下载版本:hibernate-release-4.3.11.Final 二.Hibernate jar ...

  2. (原创)开发使用Android studio所遇到的一些问题总结

    1.Android studio下载链接地址(无需FQ):包括先行版和正式版(推荐使用正式版bug少) http://www.androiddevtools.cn/ 2.第一次安装避免成功先不要急着打 ...

  3. STL源码剖析(list)

    SGI STL中list是使用环状双向链表实现的.它的结点结构定义如下: template <class T> struct __list_node { typedef void* voi ...

  4. Spring bean注入方式

    版权声明:本文为博主原创文章,如需转载请标注转载地址. 博客地址:http://www.cnblogs.com/caoyc/p/5619525.html  Spring bean提供了3中注入方式:属 ...

  5. 【服务器时间修改为东八区】包括Apache2和mysql

    1.服务器Apache时间修改,可通过修改php.ini进行修改 所以就深入了解了一下, 发现Apache(PHP)的服务器时间时区默认为UTC(Coordinated UniversalTime 世 ...

  6. jQuery改变label/input的值,改变class,改变img的src

    jQuery改变label/input的值.改变class,改变img的src jQuery改变label的值: $('#aID').text("New Value"); jQue ...

  7. Entity Framework Code First使用者的福音 --- EF Power Tool使用记之一(转载)

    好像蛮长时间没有新文章带给大家了.前几天出差再加上忙着公司里的活儿,几乎都没时间上博客园了.今天正好有些时间,为大家简单介绍EF产品组新发布的一个牛逼的小工具——EF Power Tool(翻译的话, ...

  8. unity, iterate immediate children and iterate all children

    遍历所有直接子节点(immediate children): foreach (Transform child in transform) { // do whatever you want with ...

  9. 点滴积累【C#】---使用log4net组件记录错误日志(以文本形式记录)

    效果: 描述: 利用log4net组件进行错误日志的记录,log4net记录错误的方式我所了解的有4种,No.1 文本形式记录日志,No.2存储到数据库形式记录日志,No.3控制台控制显示日志,No. ...

  10. 分页技术框架(Pager-taglib)学习二(SSH数据库分页)

    一.Pager-taglib数据库分页前提    Pager-taglib分页标签也可以实现数据库分页,与页面分页不同的是需要给后台传两个参数,一个是pageNo(当前页数)或pageOffset(偏 ...