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. 贪心-Saruman‘s Army POJ - 3069

    万恶之源 目录 题意 思路 贪心的原则是什么呢? 错解 正解 代码实现 书上的代码 我的代码 比较一下 问题 题意 给定若干个点的坐标,与范围R.每个点可以选择是否标记,标记后这个点的左右范围R内的所 ...

  2. SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多

    关于封面:晚饭后回自习室的路上 Easyexcel 官方文档 Easyexcel | github 前言 最近也是在写的一个小练习中,需要用到这个.趁着这次就将写个整合的Demo给大家. 希望能够让大 ...

  3. 转:bash shell 语法1

    1 Shell介绍 Shell的作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行一条,这种方式称为交互式(Interactive),Shell还有一种执行命令的方式称为批处理(Batc ...

  4. ARM 链接配置.lds文件学习<转>

    本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971 对于.lds文件,它定义了整个程序编译之后的连接过程,决定了 ...

  5. 【性能测试】常见的性能问题分析思路(二)案例&技巧

    上一篇介绍了性能问题分析的诊断的基本过程,还没看过的可以先看下[性能测试]常见的性能问题分析思路-道与术,精炼总结下来就是,当遇到性能问题的时候,首先分析现场,然后根据现象去查找对应的可能原因,在通过 ...

  6. Pip安装Django超时(time out)解决方法

    (ll_env)learning_log$  pip install Django  执行该命令,始终报错,如上图 解决方法如下: pip install  -i http://pypi.douban ...

  7. vue监听器watch & 计算属性computed

    侦听器watch vue中watch是用来监听vue实例中的数据变化 watch监听时有几个属性: handle:其值是一个回调函数,就是监听对象对话的时候需要执行的函数 deep:其值true 或者 ...

  8. python datetime 增减以月为单位的时间段

    datetime.timedelta(days=10)  # 可以 datetime.timedelta(months=1)   # 不可以 替代: from datetime import date ...

  9. Java发展的重大事故

    1990年,在Sun计算机公司中,由Patrick Naughton.Mi keSheridan 及 James Gosling领导的小组Green Team,开发出的新的程序语言,命名为0ak, 后 ...

  10. 【死磕 NIO】— 深入分析Buffer

    大家好,我是大明哥,今天我们来看看 Buffer. 上面几篇文章详细介绍了 IO 相关的一些基本概念,如阻塞.非阻塞.同步.异步的区别,Reactor 模式.Proactor 模式.以下是这几篇文章的 ...