写在前面
经历了一个阶段的校招,也侥幸拿到了几个offer,说实话,虽然找工作的日子很困难,但是在那一段时间也确实给自己带来了很多成长,尤其是一些自己以前独立学习的时候没有注意到的知识点,对基础的掌握要牢固了些。但是,拿到了自己想要的offer之后,自己心理上放松了很多,对学习和巩固都没有了之前的热情,直到最近几天才醒悟过来,我们应该时刻保持一定的警惕性和危机感,提升自我才是最重要的,期望能与大家共勉。
因自己的技术水平有限,本文的一些见解可能有错误之处,希望读者可以批评指正。
事件循环
javascript一门单线程的非阻塞的脚本语言
上面这一句话想必大家都听过,提取一下和本文有关的关键字单线程
&非阻塞
;
单线程
-
单线程意味着什么?
意味着javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务。 -
javascript为什么要是单线程的?
我们反向思考一下, 如果javascript是多线程的,那么当两个线程同时对dom进行一项操作,例如一个向其添加黄色背景,而另一个添加蓝色背景,此时的浏览器想必是崩溃的(浏览器:WTF?手动黑人问好脸)。所以呢,为了避免发生类似的这种情况,javascript选择只用一个主线程来执行代码,这样就保证了程序执行的一致性。 -
web worker
向来事情都不是绝对的,单线程虽然解决了上面的问题,但是劣势也是显而易见的,虽然保证了执行的顺序但是也限制了javascript的效率。所以web worker就出来了,但是web worker更类似于主线程下的子线程。利用web worker的所有新线程都受主线程的完全控制,不能独立执行,一般只能用来进行一些计算方面的操作。
非阻塞
这个就是今天的主角了,本文讲述的是浏览器环境下的事件循环,node虽然相似,但还是有些不同的,不在这篇文章的讲述范围。
先解释下关键字
-
浏览器的多线程
虽然JS是单线程的,但浏览器不是单线程的,基本上主流浏览器都至少会有javascript引擎线程
,界面渲染线程
,浏览器事件触发线程
,Http请求线程
; -
异步
简单解释即使一些无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件 -
非阻塞和异步有什么关系呢?
非阻塞即是当代码需要进行一项异步任务的时候,主线程会挂起这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调 -
执行栈
当我们调用一个方法的时候,js会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中存在着这个方法的私有作用域,上层作用域的指向,方法的参数,这个作用域中定义的变量以及这个作用域的this对象。 而当一系列方法被依次调用的时候,因为js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方。这个地方被称为执行栈。 -
事件队列
js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列即事件队列。 -
宏任务(macrotask)
包括整体代码script,setTimeout,setInterval、setImmediate及页面交互I/O事件。 -
微任务(microtask)
原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、Object.observe(已废弃)、 MutationObserver
上述的名词关键字解释也是查阅的结果,可以作为理解参照,有不正确的地方欢迎指正。
看图说话
这张图我们简单解释一下:
- 执行宏任务队列里第一个任务(第一次整体代码script就是宏任务,所以我觉得有些人说的先执行微任务后执行宏任务是不准确的),执行完后移除它;
- 执行此次宏任务执行完后所有待执行的微任务;
- 重复上述步骤;
-------------------------------未完,待续-----------------------------------