javascript的event loop事件循环

这是今天一个朋友发给我的一个面试题,

感觉还挺有意思的,

写个博客以供分享

先看看这个面试题目:

观察下面的代码,写出输出结果

console.log('0')
setTimeout(function () {
console.log('1');
}); new Promise(function(resolve,reject){
console.log('2')
resolve(3)
}).then(function(val){
console.log(val)
})
console.log(4)

输出结果: “0” “2” 4 3 “1”

今天主要是分析为什么输出结果是这样的?这就和 javascript 的执行机制密切相关了.


Event QueueEvent Loop

javascript 是一门单线程的语言, 这就意味着在执行代码的时候, 都只有一个主线程来处理所有的任务.

我们都知道 javascript 包括同步代码和异步代码, 那么 javascript 是怎么处理这两种情况的呢?

  • 同步和异步任务分别进入不同的执行 场所, 同步的进入主线程,异步的进入 Event Table 并注册函数
  • 当指定的事情完成时, Event Table 会将这个函数(回调函数)移入 Event Queue
  • 主线程内的任务执行完毕为空, 会去 Event Queue 读取对应的函数,进入主线程执行
  • 上述过程会不断重复, 也就是常说的 Event Loop(事件循环)

这里我们引进了 Event Queue 事件队列这一概念. 所有异步操作的回调都会进入到这里. 然后等到主线程空闲, 就会从这里调取回调执行.


setTimeout

setTimeout 相信大家都有使用过, 可以延时执行并且是异步执行的.

但是有时候我们得到的结果往往是代码实际执行的时间比我们想要延时执行的时间要久。这又是为什么呢?

这就和我们之前所说的 Event Loop 有关了, 我们可以来具体看下 setTimeout 的执行步骤:

setTimeout(function () {
asyncFn()
}, ); syncFn()
  • asyncFn 将异步执行函数放在 Event Table, 并且开始计时
  • 开始执行 syncFn, 但是 syncFn 可能需要处理的内容很多, 执行时间超过 1 秒, 但是计时还在继续
  • 计时到达 1 秒, setTimeout 延时完成, asyncFn 进入 Event Queue 事件队列, 但是主线程还在执行, 所以只能等待
  • syncFn 执行完成, 此时 asyncFn 从事件队列中进入主线程执行

所以有时候会出现代码实际执行时间比延时时间长的情况。


宏任务和微任务

之前我们说过异步任务会进入到事件队列中, 不同类型的任务会进入到不同的队列中, 比如宏任务会进入到宏任务队列中, 微任务会进入到微任务队列中.

微任务:promise

宏任务:setTimeout、setInterval、setImmediate

我们只要记住 当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行

这时候我们就可以解释一开始的代码执行结果了:

  • 主线程执行按顺序代码
  • 遇到 setTimeout, 回调进入到宏任务队列上
  • 遇到 Promise, 立即执行, then 函数进入到微任务队列
  • 同步代码执行结束, 主线程检查是否存在微任务, 发现 then, 执行
  • 微任务执行完毕, 再去查找宏任务 setTimeout, 执行
  • setTimeout 执行结束, 检查,不存在其他, 结束.

以上。

javascript的event loop事件循环的更多相关文章

  1. node.js中对Event Loop事件循环的理解

    javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...

  2. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  3. Event Loop事件循环,GET!

    JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...

  4. 进程,线程,Event Loop(事件循环),Web Worker

    线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...

  5. 浅谈 Event loop (事件循环)

    从Event Loop谈JS的运行机制 先来理解一个概念: JS分为同步任务和异步任务 同步任务都在主线程上执行,形成一个执行栈 Execute Content Stack 主线程之外,事件触发线程管 ...

  6. js event loop事件循环

    浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...

  7. JavaScript event loop事件循环 macrotask与microtask

    macrotask  姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...

  8. Javascript并发模型和事件循环

    Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...

  9. JavaScript 如何工作的: 事件循环和异步编程的崛起 + 5 个关于如何使用 async/await 编写更好的技巧

    原文地址:How JavaScript works: Event loop and the rise of Async programming + 5 ways to better coding wi ...

随机推荐

  1. [js]变量提升-关于条件

    条件函数变量提示于全局中函数变量提升不一样. 条件中: 函数变量提升, 只是声明(现新版本浏览器中) if(g()){ function g() { return true } console.log ...

  2. rosetta deep_analysis

    此小程序可以分析backrub,enzdes类的聚类logo分析,详细路径是: /home/wangq/Programs/rosetta_2018.09.60072_bundle/tools/prot ...

  3. sitecore开发入门Sitecore的CRUD操作 - 第一部分

    在本文中,讨论如何使用Sitecore.Data.Items.Item并对这些项执行CRUD(创建,读取,更新和删除)操作.我还将介绍如何使用Glass和Fortis类库进行相同的操作,这些操作都是对 ...

  4. JDK安装与配置(Windows 7系统)

    1.前言 安装之前需弄清JDK.JRE.JVM这几个概念,不然稀里糊涂不知道自己在装什么. (1)什么是java环境:我们知道,想听音乐就要安装音乐播放器,想看图片需要安装图片浏览器,同样道理,要运行 ...

  5. Django之CBV源码解析

    l链接跳转:https://www.cnblogs.com/hnlmy/p/9662798.html 以及https://www.cnblogs.com/hnlmy/p/10603999.html

  6. js 星星效果思路

    //星星的效果思路 1.获取需要修改的元素 ul li 跟p 布局 2.给li 加移入事件 更改提示框显示, 3.给li 加移出事件 更改提示框隐藏 4.给li加索引值代表自己的序号 5.在li移入时 ...

  7. JavaScript Dom 绑定事件

    JavaScript  Dom 绑定事件 // 先获取Dom对象,然后进行绑定 document.getElementById('xx').onclick document.getElementByI ...

  8. Linux cached过高问题

    1. cached主要负责缓存文件使用, 日志文件过大造成cached区内存增大把内存占用完 . Free中的buffer和cache:(它们都是占用内存):buffer : 作为buffer cac ...

  9. Java访问权限修饰符public protected friendly private用法总结(转载好文Mark)

    首先声明:Java中,friendly这个修饰符并没有显式的声明,在成员变量和方法前什么修饰符也不用,默认的就是friendly.为了条理清晰,分三种不同情况来总结. 一 访问权限修饰符修饰成员变量和 ...

  10. win7下MKVToolNix进行mkv字幕封装

    MKVToolNix下载地址(https://www.fosshub.com/MKVToolNix.html) 下载安装后打开,当时没创建桌面图标,GUI地址(C:\ProgramData\Micro ...