同步与非同步

刚开始学习JavaScript的时候,很单纯的认为所有程序码是逐行执行的,就像看书不都是ㄧ行一行阅读吗?直到踩到callback function 的地雷才意识到必须了解 JavaScript 具有非同步特性。

为什麽需要非同步?

JavaScript 是单线程语言,代表程序码只能一行一行执行,若上一行的程序码卡住,下一行的程序码就无法执行。

但现代网页的互动特性有些要等待使用者点击,有些时候则是需要载入第三方提供的影像等等,若是维持同步方式处理的话,当等待资源的时间过长就会造成画面卡住的现象,因此,JavaScript的设计者将所有要执行的任务分成两种:

  1. 同步 (Synchronous)
  2. 非同步(Asynchronous)

哪些是非同步?

  • setTimeout: 等待几秒後再执行
  • addEventListener: 等待触发的事件才执行
  • fetch: 发送请求,需要等待回应

JavaScript 如何做到非同步


图片来源:sessionstack

JavaScript 执行环境中有一个叫做 Call Stack 的地方,负责存放要执行的函式。

可以把 Call Stack 想成办公桌上放待办事项的地方,每天上班时,可能需要先开会,然後会议上老板交派许多任务,回到办公室後得将任务一一分类,有些任务可能需要经过其他部门审核,有些可能需要询问外部厂商,这些无法由你自己立刻处理的任务,就会给相关部门处理,完成後再放到一个叫做Callback Queue的位置。

而 Event Loop 就像一位积极的秘书,会不断观察办公桌上的代办事项完成了没,当办公桌上没有任何任务後,就会把放在 Callback Queue 中的任务放到办公桌上让你接手完成。

回到程序语言来谈,代表当程序码是浏览器提供的API时,就会丢到 Web APIs中。
像是setTimeout就会在到达设定的秒数後被放入CallBack Queue中等待,等到 Call Stack 清空後,Event Loop 就会把 setTimeout 放入Call Stack 并立即执行其中的程序码。

stack 按照後进先出(LIFO, Last In First Out)的原理运作
quene 运作方式则是先进先出(FIFO, First-In-First-Out)

console.log("决定铁人赛主题");

setTimeout(() => {
  console.log("先找一下资料");
}, 0);

setTimeout(() => {
  console.log("开始写铁人赛文章");
}, 0);

console.log("完成铁人赛文章了!");

深入认识了 Event loop 後就可以理解为什麽 setTimeout 明明设定了0秒,为什麽还是不会依序印出:

决定铁人赛主题 -> 先找一下资料 -> 开始写铁人赛文章 -> 完成铁人赛文章了!

只要记得所有非同步的事件都会先进到 Callback Queue 中,等待 Call Stack 中的任务执行完毕,才会轮到非同步的程序码执行。

参考资料:
Concurrency model and the event loop
所以说event loop到底是什麽玩意儿?
loupe
理解 JavaScript 中的事件循环、堆叠、伫列和并发模式


<<:  Best Digital Marketing Company | Immortal Business

>>:  Day17|【Git】存在 .git 目录里的东西 - Blob 物件与 Tree 物件(上)

[开发经验分享]如何中断执行中的 Task(任务)

情境 在做大数据分析时,由於需要从几千万甚至几亿笔资料中做运算,应用程序就整个不能动,若中间机器有要...

谈谈 Log 的定义以及使用 - part1

Spring Boot 内部所有日志记录是使用 Commons Logging 实现,同时默认配置也...

radio vs checkbox

延续昨天的v-model绑定,昨天我们知道他可以绑定input, textarea和select e...

10大安全软件爆漏洞

最近IThome新闻报导, 10大安全软件爆漏洞,可被骇客利用对使用者发动攻击 相关新闻报导链结 其...

18.移转 Aras PLM大小事-快速贴入ECR受影响物件

这篇一样是Excel复制了很多料号,然後贴入ECR受影响物件 左边一个输入框,右边是系统讯息,上面一...