javascript的事件循环机制
JavaScript是一门编程语言,既然是编程语言那么就会有执行时的逻辑先后顺序,那么对于JavaScript来说这额顺序是怎样的呢?
首先我们我们需要明确一点,JavaScript是单线程语言。所谓单线程的意思就是只能按照一条逻辑线来运行,譬如你上班排队上公交车,先排先上,一个接一个。
首先我们需要清楚几个名词:
1.任务队列(task queue)
script中的每一个语句都是一个任务,譬如打印语句或者变量声明语句都是一个任务。
var monkey='熏悟空';
var pig='猪八盖';
如上面的代码就可以理解为两个任务。
而任务队列就是一个有规则的任务的集合,其规则就是先进先出。
2.同步任务与异步任务
所谓的同步任务就是当主线程运行到这里就能马上执行的任务,譬如:打印语句。
而异步任务则是需要等待一定时间后才能执行的语句,在这个过程中先运行他后面的语句,打个比方是猪扒盖去叫熏悟空打妖怪,熏悟空说“呆子,你先去,我去天上偷个蟠桃,看看七仙女后就来”。异步任务中的典型例子就是setTimeout延时任务。
console.log('熏悟空');
setTimeout(function(){
console.log('猪八盖')
},1000);
console.log('撒无尽');
当我主线程运行到异步任务setTimeout时就先注册一个回调函数,该函数是setTimeout中的内容,然后就去执行srtTimeout后面的打印语句。等到1000毫秒之后再去运行之前存储的回调函数。
具体两个相结合的运行顺序就是:
- 主线程自上而下执行代码。
- 同步任务直接执行,异步任务进入到事件注册表中并注册对应的回调函数。
- 等到异步任务的延时时间到了之后,事件注册表会将对应的回调函数添加到事件队列中。
- 主线程任务执行完毕之后,再去读取事件队列中的任务,将其进入到主线程中执行。
- 以上过程,不断循环往复。
以上不断循环的过程就是事件循环。
3.微任务与宏任务
javaScript不仅分为同步任务与异步任务,从另一个角度又分为了微任务与宏任务。
首先我们只需要记住几个特殊例子,也就是仅有的几个微任务:
1.Process.nextTick:node环境下的一个方法
2.Promise.then(.catch,.finally)注意这里是Promise的几个状态捕捉函数,而不是Promise本身
3.MutationObserver:元素节点的事件监听
除此以外的任务全都是宏任务,在同一个任务队列中先运行所有的同步任务,再执行异步任务,异步任务里面又包含了微任务与宏任务,先执行微任务,再执行宏任务。
小练:
console.log('俺是熏悟空');
setTimeout(function() {
console.log('俺是猪扒盖');
}, 0);
new Promise(function(resolve,reject){
console.log('俺是撒无尽');
resolve()
}).then(function() {
console.log('俺是白聋马');
})
console.log('俺是糖酸脏');
请问打印顺序是啥?
俺是熏悟空-->俺是撒无尽-->俺是糖酸脏-->俺是白聋马-->俺是猪扒盖。
逻辑理解:
1.主线程先执行‘俺是熏悟空’的同步打印任务
2.遇到setTimeout的异步任务,将其丢入事件注册表并注册对应回调函数,先不执行‘俺是猪扒盖’的打印任务
3.遇见Promise的函数执行‘俺是撒无尽’的同步打印任务。
4.遇见Promise.then异步任务,将其丢入事件注册表并注册对应回调函数,注意此时事件注册表已经有了一个setTimeout的回调,此时Promise.then的回调该放在setTimeout回调的前面还是后面呢,答案是前面,因为Promise.then属于微任务,优先级高于属于宏任务的setTimeout,先不执行‘俺是白聋马’的打印任务
5.执行‘俺是糖酸脏’的同步打印任务。
6.任务队列执行完毕,去事件注册表将延时时间(异步时间)已经到了的异步函数对应的回调函数添加到新的任务队列,再按照逻辑进行执行,先执行微任务Promise.then的回调函数,再执行setTimeout的回调函数
7.任务队列与事件注册表均无任务与事件,执行结束
以上需要注意的是
1.setTimeout的延时时间设置的是0,但是不会因为设置的0ms就变成了同步任务,不论设置多少都是异步任务,都是宏任务,因此执行顺序在同步任务之后,也在微任务之后。
2.为什么‘俺是撒无尽’的打印任务是同步打印呢,因此Promise的那几个状态捕捉函数才是异步任务,才是微任务,Promise本身函数里面的执行部分依旧是同步任务。
javascript的事件循环机制的更多相关文章
- 对javascript EventLoop事件循环机制不一样的理解
前置知识点: 浏览器原理,浏览器内核5种线程及协作,JS引擎单线程设计推荐阅读: 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理 [FE]浏览器渲染引擎「内核」 js异步编程,Promise ...
- JavaScript的事件循环机制浅析
前言 JavaScript是一门单线程的弱类型语言,但是我们在开发中,经常会遇到一些需要异步或者等待的处理操作. 类似ajax,亦或者ES6中新增的promise操作用于处理一些回调函数等. 概念 在 ...
- 【运行机制】 JavaScript的事件循环机制总结 eventLoop
0.从个例子开始 //code-01 console.log(1) setTimeout(() => { console.log(2); }); console.log(3); 稍微有点前端经验 ...
- 深入理解JavaScript事件循环机制
前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To ...
- JavaScript 运行机制:Event事件循环机制
JavaScript Event事件循环机制 JS是单线程的,浏览器只分配一个主线程给JS.一次只能执行一个任务,当前任务执行完后在可以执行下一个任务.任务多时,就会形成任务队列排队等待执行.但是非常 ...
- javascript事件循环机制 浅尝手记
引入 众所周知Javascript是一个单线程的机制,虽然可以依托多线程的浏览器实现页面如何实现页面复杂的渲染.事件响应,但仍不会改变其单线程的本质:所以对于js的事件循环机制的了解是一个前端人员的必 ...
- 深入浅出Javascript事件循环机制
一.JS单线程.异步.同步概念 众所周知,JS是单线程(如果一个线程删DOM,一个线程增DOM,浏览器傻逼了-所以只能单着了),虽然有webworker酱紫的多线程出现,但也是在主线程的控制下.web ...
- 浏览器中的JavaScript事件循环机制
浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...
- 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)
JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...
随机推荐
- 贪心-Saruman‘s Army POJ - 3069
万恶之源 目录 题意 思路 贪心的原则是什么呢? 错解 正解 代码实现 书上的代码 我的代码 比较一下 问题 题意 给定若干个点的坐标,与范围R.每个点可以选择是否标记,标记后这个点的左右范围R内的所 ...
- SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多
关于封面:晚饭后回自习室的路上 Easyexcel 官方文档 Easyexcel | github 前言 最近也是在写的一个小练习中,需要用到这个.趁着这次就将写个整合的Demo给大家. 希望能够让大 ...
- 转:bash shell 语法1
1 Shell介绍 Shell的作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行一条,这种方式称为交互式(Interactive),Shell还有一种执行命令的方式称为批处理(Batc ...
- ARM 链接配置.lds文件学习<转>
本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971 对于.lds文件,它定义了整个程序编译之后的连接过程,决定了 ...
- 【性能测试】常见的性能问题分析思路(二)案例&技巧
上一篇介绍了性能问题分析的诊断的基本过程,还没看过的可以先看下[性能测试]常见的性能问题分析思路-道与术,精炼总结下来就是,当遇到性能问题的时候,首先分析现场,然后根据现象去查找对应的可能原因,在通过 ...
- Pip安装Django超时(time out)解决方法
(ll_env)learning_log$ pip install Django 执行该命令,始终报错,如上图 解决方法如下: pip install -i http://pypi.douban ...
- vue监听器watch & 计算属性computed
侦听器watch vue中watch是用来监听vue实例中的数据变化 watch监听时有几个属性: handle:其值是一个回调函数,就是监听对象对话的时候需要执行的函数 deep:其值true 或者 ...
- python datetime 增减以月为单位的时间段
datetime.timedelta(days=10) # 可以 datetime.timedelta(months=1) # 不可以 替代: from datetime import date ...
- Java发展的重大事故
1990年,在Sun计算机公司中,由Patrick Naughton.Mi keSheridan 及 James Gosling领导的小组Green Team,开发出的新的程序语言,命名为0ak, 后 ...
- 【死磕 NIO】— 深入分析Buffer
大家好,我是大明哥,今天我们来看看 Buffer. 上面几篇文章详细介绍了 IO 相关的一些基本概念,如阻塞.非阻塞.同步.异步的区别,Reactor 模式.Proactor 模式.以下是这几篇文章的 ...