8. 解释 Event Loop ( 下 ) --- Task Queue ( Callback Queue )

(上一篇只有复习,没有带到题目,所以这篇会解释两个问题,答案可以直接看结论~)

  1. 解释Event Loop的运作?
  2. Call Stack和Task Queue的差异?

在上一篇文章 7. 解释 Event Loop ( 上 ) --- Call Stack有提到,非同步的程序设计是为了解决单执行绪在事件的处理上,没有效率的问题。

而这篇文章的主题 —— Event Loop,就是用来控制在JS里同步与非同步事件的运行:

Event Loop 事件循环


https://ithelp.ithome.com.tw/upload/images/20210909/20129476TQdN4y0K6I.png
(以 Google Chrome的V8引擎为例。 )

解释一下这张图:

  1. JavaScript Engine本身涵盖两个Components:

    • Memory Heap — 决定object在记忆体的配置。
    • Call Stack — 程序码运行时,放置 stack frames 的地方。(负责排序同步执行函式)
  2. 许多我们在浏览器使用的API(e.g. DOM, AJAX, Timeout...),并非来自JS引擎,而是由浏览器的 Web APIs 提供。

  3. 所有被放进Async Function里,作为参数的function,被称作"callback",这些callback被依序放在 callback queue 等待执行。(负责排序非同步执行函式)

所有执行环境的共通点,就是都有一个叫"event loop"的内建机制。
它会随着时间执行上述被分类的任务,并在每次执行时调用JS引擎。

Event Loop最重要的工作,就是控制 Call StackCallback Queue(Task Queue) 的运作。

( ↑ 全文重点

+++++++++++++++++++++++++
整理一下逻辑关系:

  • Chrome(或Node.js)使用 V8 引擎;V8 引擎包含: Memory Heap 和 Call Stack。
  • 各个 Browser 提供 Web APIs 供开发者使用;Web APIs 包含 DOM, AJAX, setTimeout...等。

+++++++++++++++++++++++++

Web APIs & Callback Queue(Task Queue)


我们已经知道DOM, AJAX, Timeout...都是由Web APIs提供的API,而当我们使用这些API进行非同步的呼叫(callback function),
Event Loop 会将 callback function 放进 Callback Queue (伫列)。

( 我自己在解释的时候偏好讲Callback Queue,但因为题目写Task Queue,所以下面结论是讲Task Queue。)

Queue 伫列

伫列也是资料结构的一种,特色是先进先出(First-In-First-Out, FIFO)。
https://ithelp.ithome.com.tw/upload/images/20210909/20129476cJEyjuMT9W.png
假设物件依照a, b, c的顺序被放入,越早放入的会越早取出,所以取出的顺序也是a, b, c。

Callback Queue

A JavaScript runtime uses a message queue, which is a list of messages to be processed. Each message has an associated function which gets called in order to handle the message.

→ 直到Call Stack被清空,Event Loop会将Callback Queue里最早纪录的讯息(message)放入Call Stack,直到Callback Queue里的message也被清除完成。

这里可以执行一个例子:

    console.log('start');

    setTimeout(function callback() { 
        console.log('callback is here');
    }, 3000);

    console.log('end');

setTimeout()的执行方式
setTimeout()并不会直接将callback交给event Loop,他会先建造自己的计时器(timer),直到计时结束,才将将callback放进callback queue。

→ 因此,上面例子的3000不是指3秒後就会执行程序,而是3秒後才会被放进伫列

start
end

callback is here // 3秒後出现

然後上面的执行顺序是这样的: gif和图档(这次图片放进来反而有点乱,所以和gif的连结放在一起。)

  1. 【In Call stack】 console.log('start')放进call stack;执行console.log('start')
  2. 【In web api】 setTimeout()建立timer,等3秒...
  3. 【In Call stack】console.log('end')放进call stack;执行console.log('end')
  4. 【In web api】3秒结束,callback()进入【Callback Queue】
  5. 【In Callback Queue】Call stack被清空,进入Call stack。
  6. 【In Call stack】 callback()放进call stack;执行callback()
【In Call stack】 【In web api】 【In Callback Queue】
1 console.log('start')放进call stack;执行console.log('start') --- ---
2 --- setTimeout(callback())建立timer,等3秒...
3 console.log('end')放进call stack;执行console.log('end') ---
4 --- --- 3秒结束,callback()进入【Callback Queue】
5 callback()放进call stack;执行callback()

结论

  1. 解释Event Loop的运作?
    因为JS的执行是单执行绪的,在处理同步事件时,会将函式放在Call Stack执行。
    如果是请求资料或滑鼠点击之类的非同步事件,则会将事件交给浏览器提供的Web APIs,在解析完成後,放到Task Queue,等待Call Stack里的函式执行完毕後,再继续将Task Queue里的函式依序放入Call Stack,并完成剩余函式。

  2. Call Stack和Task Queue的差异?
    Call Stack用於同步事件的函式执行,Task Queue用於非同步事件的函式执行,而Call Stack里的工作会先被执行完毕。
    Call Stack的结构是後进先出(LIFO),越早放进Call Stack的函式会越晚被执行;而Task Queue则是先进先出(FIFO),被放进Task Queue的函式,会依照放入顺序执行。

【如内文有误还请不吝指教>< 谢谢阅览至此的各位:D】

参考资料:

-----正文结束-----

我自己是会听歌听到舍不得去睡觉的人,所以事情做不完的时候,音乐放出来我就会乖乖做下去了。
前阵子才把《La La Land》补完,但在看电影之前就很喜欢《City Of Stars》这首歌。


<<:  [Day8]PHP判断式01

>>:  问题整理(一)Day5

Day25-你的资料安全吗(三)

前言 因为资料库基本上可以分成 SQL 跟 NoSQL 两大类,昨天讲完 SQL injection...

D8 - 用 Swift 和公开资讯,打造投资理财的 Apps { 台股申购资讯实作.1 - 取得公开申购公告csv档 }

承上一篇,公开申购公告的纲页页面如下 依照我们会需要的栏位,我们的 model 如下 // // S...

Day01 - 随意玩之 Spec 相关测试

看到有永丰金融 API 可以玩,於是就下定决心报名了~ 报名非常简单,填一下资料马上就在 E-MAI...

Using Lombok in IDEA

USing Lombok in IDEA ...

React 运作原理 & JSX

React 运作原理 在原生的 JavaScript 里,我们会操作 DOM 来修改网页程序码,但这...