同步、非同步事件控制

这篇要延伸上一篇提到的单执行绪 ( single thread ),来讲同步 synchronous 与非同步 asynchronous。
面试还蛮常被问到「请你解释同步、非同步」、「什麽是 Event Loop」之类的~

JS 作为一门单执行绪语言,其程序码在执行的时候,一个时间点仅能做一个指令,这也是我们常说的「同步」。初学时对同步这个词一定很疑惑,听起来很像可以同时做很多事情,结果刚好相反

◢▆▅▄▃ 崩╰(〒皿〒)╯溃▃▄▅▆◣ ,不过别担心,写久了就习惯了!


单执行绪:任务执行时是依序排队处理
同步:一次只执行一件事情

以上两个是 JS 本身的语言特性所规范的事情,其实这两个名词我觉得都是在讲同个概念

非同步:看似可以同时执行多个事情
为什麽说是看似呢?因为这些非同步事件在伫列中还是会依序被叫到 call stack。

那麽重点来了,作为一个具有同步特性的语言,如何做到非同步?非同步又指什麽?

例如我们浏览网站的时候,网站内容几乎是透过後端给予或者用 API 获取第三方的资料,但这种动作我们是没有办法预估该事件多久内可以完成,且 JS 又是同步的,难道要等它载完才能够做其他动作吗?这是不太不可能的~

这时候 JS 就请到浏览器大大来帮忙,请浏览器提供非同步事件的 API (Web APIs),并在背後运行的时候多开一个区域放置这些「需要较多时间处理,无法预估处理时间的事件」,这个区域我们称为事件伫列 Event Queue。

Web API 目前大致有这几种:

  • Event listeners 监听事件
  • Timer 计时有关的方法 - setTimeout、setInterval
  • Ajax - XHR、Fetch

除此之外,在 ES6 新增的 Promise 方法也是用来处理非同步请求,而且优先级别高於 Web API。

用图简言之
https://ithelp.ithome.com.tw/upload/images/20210915/20141763AAZ8pQNvRc.png

浏览器会把非同步事件放置在 event queue 里,透过 event loop 来协调,当 call stack 里的同步事件都处理完毕後,就会把 queue 里的非同步事件调回到 call stack 执行。

请记得 call stack 才是真正执行的地方,其他都是等待区。

最近刚好看到 Linked 上的图片分享,可惜这里没法发 gif 档
https://ithelp.ithome.com.tw/upload/images/20210915/20141763pY1NReBL9Y.png
总之就是事件执行的顺序跟 TASK 的编号是一样。
其中 Microtask 跟 Macrotask 就是 Promise 事件的优先度会大於 Web API 事件。

另外补充一个小地方,call stack 我们都记得是後进先出,但 queue 是先进先出,也就是先进来的事件会第一个被调到 call stack 执行。


最後用一个考到烂的经典考题来结尾 (゚д⊙)

可以先自己想一下哦!

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}

ANS:

https://ithelp.ithome.com.tw/upload/images/20210915/20141763tczIk2cXnk.png

首先第一个 for 回圈,for 本身是同步事件,所以立马就会放入 call stack 执行,但是执行发现遇到了非同步的 setTimeout() ,於是这个 setTimeout() 被移到 event queue 里。

这个回圈跑了三次,也就是有三个 setTimeout() 等在 event queue 里,接着透过 event loop 调到 call stack 执行。但为什麽是三个 3?因为我们用 var 去宣告变数 i,待同步的 for 跑完後,变数 i 为 3。加上三个 setTimeout() 并没有自己的变数 i,因此透过作用域链向外寻找 i 的身影,所以都是 3。

与第一个 for 不同,第二个 for 透过 let 来宣告,let 的特性是区块作用域,所以会保存当前的变数在每个 setTimeout() 内,所以是 0、1、2。

通常这个考题是会被接着询问的,大家可以想一下,如果不用 let ,还有什麽方法可以确保 i 的值为 0、1、2 ?


<<:  Day 15 关键字二三事

>>:  虹语岚访仲夏夜-1(专业的小四篇)

[day6] AES-CBC 内文加密机制(Message)

讯息文本使用AES-CBC模式加密传送,接收的结果亦以相同规则加密 必要的参数 如何取得 JSON讯...

Day 17. UX/UI 设计流程之五:GUI Design (上)

规划设计完 Wireflow 产出关键蓝图规格稿之後,基本上已经完成了整个产品的骨架。接着就是要根据...

【资料结构】图的表示方式与基本运作

图的基本定义 图的表示方式与基本运作 表示方式 相邻矩阵 若G(V,E)是含n个顶点的图,表示图G的...

JavaScript基本功修练:Day30 - AJAX常遇上的同源政策问题与解决方法

经过这几天学习AJAX,对於接API开始有点认识了,虽然有把一些例子顺利写出来跟大家分享,但是背後也...

Google Meet 麦克风问题

lenovo ideapad 300-15ISK Windows 10 home (重新安装两次过)...