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

おっさんでもわかる Javascriptのナゾ仕様

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Guarneri009 Guarneri009
June 01, 2023
1.3k

おっさんでもわかる Javascriptのナゾ仕様

Avatar for Guarneri009

Guarneri009

June 01, 2023
Tweet

Transcript

  1. ©Project PLATEAU / MLIT Japan 高見英和 自己紹介 Takami Hidekazu • 兵庫県生まれ、20年以上前に札幌に移住

    • 医療関連企業で薬剤割付システムや創薬シス テムを開発していたがMierune MeetUpを みて転職 • 夏季はロードバイクで走りまくっていて、冬季 もZWIFT(室内サイクリング)でローラーを回 してます • 超レイトスターターのバイオリン弾き 5
  2. ©Project PLATEAU / MLIT Japan 言語別 非同期処理の違い ⚫ C/C++ ◦

    非同期といえばスレッド作成して処理をぶん投げる ◦ 同期したい場合はセマフォやミューテックスなどを使う 10
  3. ©Project PLATEAU / MLIT Japan 言語別 非同期処理の違い ⚫ C/C++ ◦

    非同期といえばスレッド作成して処理をぶん投げる ◦ 同期したい場合はセマフォやミューテックスなどを使う ⚫ Javascript ◦ async/await 11
  4. ©Project PLATEAU / MLIT Japan C/C++で非同期処理を書いてみる (がんばってモダンC++14) #include <iostream> #include <thread>

    constexpr int TIME_TO_SLEEP1 = 500; constexpr int TIME_TO_SLEEP2 = 1000; auto async_func() { for (auto i = 0; i < 10; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(TIME_TO_SLEEP1)); std::cout << "非同期処理 c++ async_func" << i << std::endl; } return 0; } int main(int argc, char const *argv[]) { std::cout << "==== start ====" << std::endl; auto work_thread = std::thread([]{ async_func(); }); for (auto i = 0; i < 5; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(TIME_TO_SLEEP2)); std::cout << "非同期処理 c++ mainFunc" << i << std::endl; } work_thread.join(); return 0; } 13
  5. ©Project PLATEAU / MLIT Japan Javascriptで非同期処理を書いてみる  // ビジーwaitを使う方法 function sleep(waitMsec)

    { var startMsec = new Date(); // 指定ミリ秒間だけループさせる(CPUは常にビジー状態) while (new Date() - startMsec < waitMsec); } function async_func() { setTimeout(() => { for (let i = 0; i < 10; ++i) { sleep(500) console.log(`非同期処理 javascript async_func ${i}`); } }, 0) } function main() { console.log(`==== start ====`); async_func(); for (let i = 0; i < 5; ++i) { sleep(1000) console.log(`非同期処理 javascript main ${i}`); } } main(); 14
  6. ©Project PLATEAU / MLIT Japan そもそも非同期処理の考え方が違うのでは ◦ C/C++  ▪ スレッドを並列させて処理速度を上げる

    ▪ 同時並行で処理させる(ソケット通信とか、WEBサーバーとか) ◦ Javascript ▪ シングルスレッドだけど処理中のブロックを避けたい (ノンブロッキング) 18
  7. ©Project PLATEAU / MLIT Japan Javascript非同期処理 今昔物語 非同期処理を書くには3つのパターンがある。 1. コールバック関数を連ねる。 俗

    にいう、コールバック 地 獄 に 陥 る 2. Promiseができたので  Promise  then thenで繋げる ECMAScript(ES2015 / ES6) 3. async await ができたのでスッキリ書ける。 ECMAScript(ES2017 / ES8) 19
  8. ©Project PLATEAU / MLIT Japan 以下のコードを実行すると、どの順番でメッセージが表示される? function a0() { console.log("Mierune")

    } setTimeout(function a1() { console.log("です。") }, 10); a0(); Promise.resolve() .then(function b1() { console.log("一緒に") }) .then(function b2() { console.log("仲間を") }); setTimeout(function a2() { console.log("募集中") }, 0); Promise.resolve() .then(function c1() { console.log("働いてくれる") }) .then(function c2() { console.log("絶賛") }); console.log("では") 22
  9. ©Project PLATEAU / MLIT Japan 理解するには  理解するには内部を理解する必要があった • コールスタック              後入れ先出し LIFO

    (Last-In-First-Out) • タスクキュー(マクロタスクキュー) 先入れ先出し FIFO (First-In-First-Out) • マイクロタスクキュー          先入れ先出し FIFO (First-In-First-Out) • イベントループ 優先順位は以下 • コールスタック=>実行 • マイクロタスクキュー (コールスタックが空の場合)=>コールスタック=>実行 • タスクキュー(コールスタックが空の場合)=>コールスタック=>実行   setTimeout関数などは指定した時間が経過したらコールバック関数をタスクキューに入れる  Promiseのコールバック関数は即座にマイクロタスクキューに関数を入れる 23
  10. ©Project PLATEAU / MLIT Japan まとめ 非同期を理解するには 26 1. シングルスレッドであること

    2. Promiseコールバック 関 数 、async 関 数 はマイクロスタックキューに 積 まれ 優 先 的 に 処 理 される。 3. set(Timeout,interbal,Immediate) 関 数 はタスクキューに 積 まれ マイクロスタックキューが空になってから処理される。 4. 可 視 化 ツールでためしてみる (https://www.jsv9000.app/)
  11. ©Project PLATEAU / MLIT Japan Pythonで非同期処理を書いてみる  MieruneではPythonを利用してバックエンド処理をすることが多い 28 import threading

    import time def async_func(): for i in range(10): time.sleep(0.5) print(f"非同期処理 python async_func {i}") def main(): print("==== start ====") work_thread = threading.Thread(target=async_func) work_thread.start() for i in range(5): time.sleep(1) print(f"非同期処理 python main_func {i}") work_thread.join() main() import asyncio import time import warnings warnings.filterwarnings('ignore') async def async_func(): asyncio.sleep(0) for i in range(10): time.sleep(0.5) print(f"非同期処理 python single async_func {i}") async def main(): print("==== start ====") async_task = asyncio.create_task(async_func()) for i in range(5): time.sleep(1) print(f"非同期処理 python single main_func {i}") asyncio.run(main()) スレッドを利用(マルチスレッド) asyncを利用(シングルスレッド)