一、四个概念

1、Javascript是单线程

单线程意味着我们的js代码只能从上往下同步执行,同一时间只能执行一个任务,这会导致某些执行时间较长或者执行时间不确定的任务会卡住其它任务的正常执行,Event Loop出现的原因正是为了解决此问题。

2、任务队列

为了解决上述的排队问题,有了任务队列,浏览器在异步任务有了结果后,将其添加到任务队列,以待将来执行,其他任务就在主线程上同步执行。

这里要注意的是,向任务队列中添加任务的时机是异步任务有结果后。其实任务队列中存在的就是异步任务的回调函数。

3、同步任务、异步任务

Js程序中的同步任务是指在主线程中执行的任务,异步任务是指进入任务队列中的任务

4、Javascript执行栈

所有的同步任务都在主线程上执行,行成一个执行栈。当主线程上任务执行完毕后,从任务队列中取出任务执行。

var name = "zhouwei";

setTimeout(() => {
    console.log(1);
}, 1000);

console.log(name);


上面代码在浏览器中执行如下,我们将程序全局执行环境的代码理解为包裹在一个main函数中的代码,这段代码的执行栈变化如下图:

  • 开始执行代码,将main任务(全局代码入栈执行),当遇到异步任务(setTimeout后)。
  • 浏览器接管异步任务,并在1s后将异步任务的结果(回调函数)添加到任务队列。
  • 执行栈中的同步任务执行完毕,此时任务队列为空(未到1s),执行栈也为空
  • 异步任务有结果后,首先进入任务队列排队(因为可能有很多异步任务)。
  • 执行栈从任务队列中取出任务开始同步执行。
  • 重复执行第5步。

二、Event Loop

Js执行栈不断的从任务队列中读取任务并执行的过程就是Event Loop

我们知道任务队列中存放的是异步任务的结果,那么异步任务都有哪些了?

  • 1、事件

Javascript中的事件有很多,都是属于异步任务。由浏览器接管,当事件触发时,将事件的回调加入的任务队列中,在Js执行栈中没有任务时执行。

  • 2、Http请求
  • 3、定时器
  • 4、requestAnimationFrame等

宏任务(macrotask)和微任务(microtask)
在了解了任务队列和Event Loop后,我们知道了Js执行栈从任务队列中读取任务执行,但这个具体工程我们任务不清楚,这里引出了宏任务和微任务的的概念,帮助我们理解Event Loop。

进入任务队列中的异步任务回调分为了宏任务和微任务, Js执行栈执行宏任务和微任务的规则如下图所示。

Js执行栈首先执行一个宏任务(全局代码) -> 从任务队列中读取所有微任务执行 -> UI rendering(浏览器渲染界面) -> 从任务队列读取一个宏任务 -> 所有微任务 -> UI rendering -> …

在每一轮的Event Loop结束后(1个宏任务 所有微任务),浏览器开始渲染界面(如果有需要渲染的UI,否则不执行UI rendering),在UI rendering结束后,开始下一轮Event Loop。

哪些是宏任务?

  • setTimeout
  • setInterval
  • setImmediate (Node)
  • requestAnimationFrame (浏览器)
  • I/O (事件回调)
  • UI rendering (浏览器渲染)

哪些是微任务?

  • Promise
  • process.nextTick (Node)
  • MutationObserver (现代浏览器提供的用来检测 DOM 变化的网页接口)

setTimeout延时问题

一般来说在代码中setTimeout中回调的执行时间都是大于设置的时间。 这是因为在setTimeout指定时间到达后,虽然回调函数被添加到了任务队列,但是此时Js执行栈中可能有正在执行的任务,此回调需要等待Js执行栈的任务执行完毕后才有机会执行,这就是setTimeout延时问题。

三、实战

练习下下方代码输出结果吧:

console.log(1);

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});

new Promise(resolve => {
    console.log(4);
    setTimeout(() => {
        console.log(5);
    });
    resolve(6)
}).then(data => {
    console.log(data);
})

setTimeout(() => {
    console.log(7);
})

console.log(8);

用上方的我们说过的js执行机制来分析这道题:

1: 执行全局任务中的同步代码输出:

1
4
8

这里需要注意的是Promise接受的handle函数是同步任务,而then方法是异步任务,所以会直接输出4。

2: 这时的任务队列中有三个setTimeout的宏任务,和一个Promise的微任务

// 此时的宏任务是

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});

setTimeout(() => {
    console.log(5);
});


setTimeout(() => {
    console.log(7);
})

// 此时微任务是
then(data => {
    console.log(data);
})

执行一个微任务, 输出:6

3: 接着执行第一个宏任务

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});


输出:2

在此宏任务中,向任务 队列添加了一个微任务。此时任务队列有了新的微任务。

4:执行一个微任务,输出:3

then(() => {
   console.log(3)
});


5: 继续按照规则执行任务, 输出: 5、7

整体输出情况是:

1、4、8、6、2、3、5、7

你的答案是不是这样呢?

总结:

  • javascritp的任务分为同步任务和异步任务
  • 同步任务在主线程(Js执行栈)中执行,异步任务被其他线程接管,并在异步任务有结果后,将其回调添加到任务队列。
  • 任务队列中的任务分为了宏任务和微任务。Js执行栈总是先执行一个宏任务,再执行完所有微任务…

到此这篇关于Javascript运行机制之Event Loop的文章就介绍到这了,更多相关Javascript运行机制Event Loop内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Javascript运行机制之Event Loop的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  6. 浅谈html5之sse服务器发送事件EventSource介绍

    本篇文章主要介绍了浅谈html5之sse服务器发送事件EventSource介绍,具有一定的参考价值,有兴趣的可以了解一下

  7. html5简介_动力节点Java学院整理

    这篇文章主要介绍了html5简介,用于指定构建网页的元素,这些元素中的大多数都用于描述网页内容,有兴趣的可以了解一下

  8. HTML5 拖放(Drag 和 Drop)详解与实例代码

    本篇文章主要介绍了HTML5 拖放(Drag 和 Drop)详解与实例代码,具有一定的参考价值,有兴趣的可以了解一下

  9. HTML中实现音乐或视频自动播放案例详解

    由于期末大作业我想插入一个背景音乐,实现点开网页就会自动播放音频的效果,今天通过本文给大家分享下我基于HTML实现音乐或视频自动播放功能,代码简单易懂,需要的朋友参考下吧

  10. ios – Swift中的非响应流委托

    所以我在Swift中使用套接字并试图将应用程序与我的服务器连接起来.我让应用程序连接到服务器的IP地址,并在服务器上使用netcat进行测试.在执行期间,应用程序的控制台输出显示它已成功连接到服务器.但是,流委托似乎没有响应.当我输入netcat时,app控制台没有打印任何内容.我已经搜索了很长一段时间,发现我的实现与其他实现非常相似.也许我在这里遗漏了一些我看不到的东西.任何想到这个问题的人都将不胜感激!

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部