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的事件循环机制的更多相关文章

  1. 对javascript EventLoop事件循环机制不一样的理解

    前置知识点: 浏览器原理,浏览器内核5种线程及协作,JS引擎单线程设计推荐阅读: 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理 [FE]浏览器渲染引擎「内核」 js异步编程,Promise ...

  2. JavaScript的事件循环机制浅析

    前言 JavaScript是一门单线程的弱类型语言,但是我们在开发中,经常会遇到一些需要异步或者等待的处理操作. 类似ajax,亦或者ES6中新增的promise操作用于处理一些回调函数等. 概念 在 ...

  3. 【运行机制】 JavaScript的事件循环机制总结 eventLoop

    0.从个例子开始 //code-01 console.log(1) setTimeout(() => { console.log(2); }); console.log(3); 稍微有点前端经验 ...

  4. 深入理解JavaScript事件循环机制

    前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To ...

  5. JavaScript 运行机制:Event事件循环机制

    JavaScript Event事件循环机制 JS是单线程的,浏览器只分配一个主线程给JS.一次只能执行一个任务,当前任务执行完后在可以执行下一个任务.任务多时,就会形成任务队列排队等待执行.但是非常 ...

  6. javascript事件循环机制 浅尝手记

    引入 众所周知Javascript是一个单线程的机制,虽然可以依托多线程的浏览器实现页面如何实现页面复杂的渲染.事件响应,但仍不会改变其单线程的本质:所以对于js的事件循环机制的了解是一个前端人员的必 ...

  7. 深入浅出Javascript事件循环机制

    一.JS单线程.异步.同步概念 众所周知,JS是单线程(如果一个线程删DOM,一个线程增DOM,浏览器傻逼了-所以只能单着了),虽然有webworker酱紫的多线程出现,但也是在主线程的控制下.web ...

  8. 浏览器中的JavaScript事件循环机制

    浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...

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

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

随机推荐

  1. Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并

    题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...

  2. (二)FastDFS 高可用集群架构学习---搭建

    一.单group 单磁盘 的 FastDFS 集群 a.前期准备 1.系统软件说明: 名称 说明 CentOS 7.x(安装系统) libfastcommon FastDFS分离出的一些公用函数包 F ...

  3. Mysql 5.7 集群部署,keepalived

    参考文章: https://blog.csdn.net/f18770366447/article/details/80703347 https://www.cnblogs.com/benjamin77 ...

  4. laravel groupby 报错

    报错信息 laravel which is not functionally dependent on columns in GROUP BY clause; this is incompatible ...

  5. 重装系统——联想window 10

    大四了,读了四年大学,唉,混的,啥也不会,工作也找不到,真的不知道这大学四年到底干了什么.专业是计算机方向的,但居然,不敢,也不会装电脑系统,大学四年的文件都是乱放的,更那个的是,有些软件卸载不完全, ...

  6. centos 添加sudo 权限

    https://apple.stackexchange.com/a/82527 visudo user1    ALL=(user2) NOPASSWD: /bin/bash amy  ALL=(AL ...

  7. 论文解读(DeepWalk)《DeepWalk: Online Learning of Social Representations》

    一.基本信息 论文题目:<DeepWalk: Online Learning of Social Representations>发表时间:  KDD 2014论文作者:  Bryan P ...

  8. Chrome handless无界面浏览器的脚本操作

    1.什么是Phantomjs (已经停止更新) 是一个无界面的浏览器 支持页面元素查找,js的执行等 由于不进行css和gui渲染,运行效率要比真实的浏览器要快很多 2.如何使用Phantomjs? ...

  9. 从零搭建vsftpd

    先吐槽一下这个工具,配置繁琐,限制规则复杂,报错信息不够详细,学起来吃力. 准备工作 [root@vsftp-server ~]# mkdir /data/ #创建ftp目录 [root@vsftp- ...

  10. C++的重载操作符(operator)介绍

    原文转载至:https://blog.csdn.net/liitdar/article/details/80654324 https://blog.csdn.net/liitdar/article/d ...