Upgrade to Pro — share decks privately, control downloads, hide ads and more …

シングルな Javascript の非同期処理

シングルな Javascript の非同期処理

Jeongmin LEE

June 27, 2024
Tweet

More Decks by Jeongmin LEE

Other Decks in Programming

Transcript

  1. // 一定時間が経ってから func を実行する function sleep(func, delay) {  const delayUntil

    = Date.now() + delay;  while (Date.now() < delayUntil);  func() } function foo() {  console.log("foo") } function bar() {  console.log("bar") } sleep(foo, 3000) // 3秒経ってから foo を実行する bar() 同期処理
  2. function foo() {  console.log("foo") } function bar() {  console.log("bar") }

    // setTimeout は一定時間が経ってからコールバック関数 foo を実行する setTimeout(foo, 3000) bar() 非同期処理
  3. Javascript はどこで実行されますか? - Web Browser - Node.js - Deno -

    Bun 、、などなど(他にもたくさんある) Image From wikipedia
  4. - Web Browser - Node.js - Deno - Bun 今回メインで話す

    Javascript はどこで実行されますか? 、、などなど(他にもたくさんある) Image From wikipedia
  5. - Web Browser - Node.js - Deno - Bun Javascript

    が実行される環境はすべて Javscript Engine を持ってる Javascript はどこで実行されますか? 、、などなど(他にもたくさんある) Image From wikipedia
  6. - Web Browser - Node.js - Deno - Bun Javascript

    が実行される環境はすべて Javscript Engine を持ってる Javascript はどこで実行されますか? 、、などなど(他にもたくさんある) JavaScriptのコードを実行する コンピュータプログラム Image From wikipedia
  7. Memory Heap Call Stack (3) i 発見 console.log(i) (2) i

    ってなんだ、heap から探そう i = "あああああ" なんとなくこんなイメージ *実際にこの形で保存される  わけではありません
  8. Memory Heap Call Stack i = "あああああ" (4) 実行!されたら Call

    Stack から消える なんとなくこんなイメージ *実際にこの形で保存される  わけではありません
  9. 補足2)関数も後でコールされたものが先に実行される Call Stack function multiply(a, b) { return a *

    b } function square(n) { return multiply(n, n) } function printSquare(n) { const square = square(n) console.log(square) } printSquare(4)
  10. 補足2)関数も後でコールされたものが先に実行される Call Stack function multiply(a, b) { return a *

    b } function square(n) { return multiply(n, n) } function printSquare(n) { const square = square(n) console.log(square) } printSquare(4) printSquare(4) square(n) multiply(n, n) ②コール ①コール ③コール ①コール ②コール ③コール
  11. 補足2)関数も後でコールされたものが先に実行される Call Stack function multiply(a, b) { return a *

    b } function square(n) { return multiply(n, n) } function printSquare(n) { const square = square(n) console.log(square) } printSquare(4) printSquare(4) square(n) multiply(n, n) ③実行 ②実行 ①実行 ②実行 ③実行 ①実行
  12. (大事)Javascript Engine はひとつの Call Stack を持つ Memory Heap Call Stack

    = シングルスレッド = Call Stack がひとつ = 一度に一つの関数コールしか処理できない
  13. Memory Heap Call Stack え、、? Call Stack ひとつなら そもそも非同期処理できなくね??? 🤔

    = シングルスレッド = Call Stack がひとつ = 一度に一つの関数コールしか処理できない (大事)Javascript Engine はひとつの Call Stack を持つ
  14. Memory Heap Call Stack console.log(1+1) まずは非同期処理を実行してみよう ①実行 ①実行 (されて CallStack

    から消える) console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3)
  15. console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) Memory Heap

    Call Stack setTimeout(function () { console.log(2+2) }, 2000) まずは非同期処理を実行してみよう ②実行 ②実行
  16. console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) Memory Heap

    Call Stack setTimeout(function () { console.log(2+2) }, 2000) まずは非同期処理を実行してみよう ②実行 ②実行 Call Stack ひとつしかないし、 setTimeout で2待つから次の console.log(3+3) は setTimeout が 終わるまで実行されないのでは、、? 🤔
  17. Memory Heap Call Stack まずは非同期処理を実行してみよう 結論:そんなことない console.log(1+1) 実行 console.log(3+3) 実行

    2秒後 console.log(2+2) 実行 console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3)
  18. Memory Heap Call Stack Web APIs Task Queue Event Loop

    ブラウザの中はざっくりこんな感じ
  19. Memory Heap Call Stack Web APIs Task Queue Event Loop

    非同期処理はざっくりこんな感じ console.log(1+1) (されて CallStack から消える) ①実行 console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ①実行
  20. Memory Heap Web APIs Event Loop setTimeout(function () { console.log(2+2)

    }, 2000) ②実行 非同期処理は大体こんな感じ Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ②実行 Task Queue
  21. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ setTimeout(function () {

    console.log(2+2) }, 2000) こっちに移動する (Call Stack じゃなくてここで2秒待つ) Call Stack setTimeout(function () { console.log(2+2) }, 2000) console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ②実行 Task Queue
  22. Memory Heap Web APIs Event Loop setTimeout が実行されたとみなされ、 Call Stack

    からは消える 非同期処理は大体こんな感じ setTimeout(function () { console.log(2+2) }, 2000) Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ②実行 Task Queue
  23. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ console.log(3+3) ③実行 (されて

    CallStack から消える) setTimeout(function () { console.log(2+2) }, 2000) Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ③実行 Task Queue
  24. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ setTimeout(function () {

    console.log(2+2) }, 2000) 2秒待ち終わったら、、 Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) Task Queue
  25. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ function () {

    console.log(2+2) } コールバック関数を Task Queue に送る Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) Task Queue
  26. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ function () {

    console.log(2+2) } Call Stack が空だったら、 Queueでまってるコールバック関数を Call Stack に移動させ、実行 Call Stack console.log(1+1) setTimeout(function () { console.log(2+2) }, 2000) console.log(3+3) ④実行 Task Queue
  27. Memory Heap Web APIs Event Loop 非同期処理は大体こんな感じ console.log(1+1) setTimeout(function ()

    { console.log(2+2) }, 2000) console.log(3+3) Call Stack という流れでこうなる Task Queue
  28. 何が Web APIs に送られる? - タイマー処理(setTimeout、setInterval など) - HTTPリクエスト(XMLHttpRequest, fetch

    など) - イベントハンドラー 、、などなど Memory Heap Call Stack Web APIs Task Queue Event Loop
  29. 何が Web APIs に送られる? Memory Heap Call Stack Web APIs

    Event Loop 特定条件を満されるまで待ってから コールバック関数実行させたい 処理が Web APIs に行くイメージ - タイマー処理(setTimeout、setInterval など) - HTTPリクエスト(XMLHttpRequest, fetch など) - イベントハンドラー 、、などなど Task Queue
  30. Task Queue とは Memory Heap Call Stack Web APIs Event

    Loop 特定条件を満されたらコールバックが Queueに移動、実行されるのを待つ 特定条件を満されるまで待ってから コールバック関数実行させたい 処理が Web APIs に行くイメージ Task Queue - Event Queue、Callback Queue ともいうらしい - 非同期処理後に実行されるコールバック関数たちの待合室
  31. Memory Heap Call Stack Web APIs Task Queue Event Loop

    なんとなくこんな感じ button.addEventListener('click', function() { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) ①実行 ①実行
  32. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) ①実行 こっちに移動する なんとなくこんな感じ Task Queue
  33. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) ②実行 setTimeout(function () { console.log(10) }, 2000) ②実行 なんとなくこんな感じ Task Queue
  34. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) こっちに移動する なんとなくこんな感じ Task Queue
  35. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) 2秒経った時に button クリックもした! なんとなくこんな感じ Task Queue
  36. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) function () { console.log(10) } function() { console.log('clicked'); } 順番にQueueに入る なんとなくこんな感じ 2秒経った時に button クリックもした! Task Queue
  37. Memory Heap Call Stack Web APIs Event Loop button.addEventListener('click', function()

    { console.log('clicked'); }) setTimeout(function () { console.log(10) }, 2000) button.addEventListener(' click', function() { console.log('clicked'); }) function () { console.log(10) } function() { console.log('clicked'); } Call Stack が空だったら、Queueで 待ってるコールバック関数たちを送る なんとなくこんな感じ Task Queue
  38. Memory Heap Call Stack Web APIs Task Queue Event Loop

    (大事) Call Stack が空なときだけ Queue でまってる子たちが Call Stack に行ける button.addEventListener(' click', function() { console.log('clicked'); }) function () { // なんかずっとやってる } function() { console.log('clicked'); } もし Call Stack が空じゃなかったら、 Queue のタスクは Call Stack に来れない Call Stackに行けない、、
  39. Memory Heap Call Stack Web APIs Event Loop だからブラウザで重い処理をしてはいけないのだ 10秒ぐらいかかる

    めちゃ重い計算処理 まってる処理1 こいつがおわるまでなにもできない 例)ボタンクリックしてもなにも起きない まってる処理2 まってる処理3 まってる処理4 Call Stackに行けない、、 Webサイトが明らかに遅いとか、 なんかクリックしても時差で実行 されるのは Call Stack が詰まってる ということでしょう、、 Task Queue
  40. Event Loop とは - Call Stack と Queue をモニタリングしてる -

    Call Stack が空いてて、 Queue で待ってるタスクがある場合 Call Stack にタスクを移動させる Memory Heap Call Stack Web APIs Event Loop Task Queue
  41. console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) Memory Heap

    Call Stack Web APIs Task Queue Event Loop setTimeout で 0 秒を待たせてみた 0 秒待つ = 待たないだから、 1、2、3 順に出力されそうな?感じ?
  42. Memory Heap Call Stack Web APIs Event Loop setTimeout で

    0 秒を待たせてみた 結論:そんなことない console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) Task Queue
  43. console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) Memory Heap

    Call Stack Web APIs Event Loop なんでそうなるのか ①実行 (されて CallStack から消える) console.log(1) ①実行 Task Queue
  44. console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) Memory Heap

    Call Stack Web APIs Event Loop なんでそうなるのか setTimeout(function () { console.log(2) }, 0) Call Stackに入る ②実行 Task Queue
  45. Memory Heap Call Stack Web APIs Event Loop setTimeout(function ()

    { console.log(2) }, 0) こっちに移動する (待ち時間が0秒だろうが 1時間だろうが関係ない) console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) ②実行 なんでそうなるのか Task Queue
  46. Memory Heap Call Stack Web APIs Event Loop setTimeout で

    0 秒を待たせてみた function() { console.log(2) } 0秒後 Queue に入る console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) ②実行 Task Queue
  47. Memory Heap Call Stack Web APIs Event Loop setTimeout で

    0 秒を待たせてみた console.log(3) function() { console.log(2) } Call Stack は次の同期処理をやる console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) ③実行 Call Stack が空に なるのを待つ Task Queue
  48. Memory Heap Call Stack Web APIs Event Loop setTimeout で

    0 秒を待たせてみた function() { console.log(2) } Call Stack が空いたらコールバック関数が Call stack に入り、実行される console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) ④実行 Task Queue
  49. Memory Heap Call Stack Web APIs Event Loop setTimeout で

    0 秒を待たせてみた console.log(1) setTimeout(function () { console.log(2) }, 0) console.log(3) Task Queue という流れでこうなる
  50. - youtube, 「What the heck is the event loop anyway?」,

    Philip Robert, https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=255s, (2024.06.27) - youtube, 「개발자 90%가 모르는 자바스크립트 동작원리 (Stack, Queue, event loop)」,https://www.youtube.com/watch?v=v67LloZ1ieI&t=191s, (2024.06.27) - 이웅모, 『모던 자바스크립트 Deep Dive : 자바스크립트의 기본 개념과 동작 원리』, 위키북스 , 2020 参考資料