Slide 1

Slide 1 text

©OpenStreetMap contributors Hidekazu Takami おっさんでもわかる Javascriptのナゾ仕様 1

Slide 2

Slide 2 text

©Project PLATEAU / MLIT Japan   題名が良くないので 2

Slide 3

Slide 3 text

©Project PLATEAU / MLIT Japan   タイトル変更させてください 3

Slide 4

Slide 4 text

©OpenStreetMap contributors Hidekazu Takami おっさん(私)がわかった Javascriptのナゾ仕様 4

Slide 5

Slide 5 text

©Project PLATEAU / MLIT Japan 高見英和 自己紹介 Takami Hidekazu ● 兵庫県生まれ、20年以上前に札幌に移住 ● 医療関連企業で薬剤割付システムや創薬シス テムを開発していたがMierune MeetUpを みて転職 ● 夏季はロードバイクで走りまくっていて、冬季 もZWIFT(室内サイクリング)でローラーを回 してます ● 超レイトスターターのバイオリン弾き 5

Slide 6

Slide 6 text

©Project PLATEAU / MLIT Japan   Javascript 6

Slide 7

Slide 7 text

©Project PLATEAU / MLIT Japan   単純だけにかえって難しい 7

Slide 8

Slide 8 text

©Project PLATEAU / MLIT Japan おっさん(私)が不思議だなと思ったJavascriptの仕様 ⚫ this ⚫ プロトタイプチェーンで継承 ⚫ 非同期処理 8

Slide 9

Slide 9 text

©Project PLATEAU / MLIT Japan おっさん(私)が不思議だなと思ったJavascriptの仕様 ⚫ this ⚫ 継承とプロトタイプチェーン ⚫ 非同期処理 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

©Project PLATEAU / MLIT Japan あしんくあうぇいと? 12

Slide 13

Slide 13 text

©Project PLATEAU / MLIT Japan C/C++で非同期処理を書いてみる (がんばってモダンC++14) #include #include 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

Slide 14

Slide 14 text

©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

Slide 15

Slide 15 text

©Project PLATEAU / MLIT Japan C++ 15 Javascript

Slide 16

Slide 16 text

©Project PLATEAU / MLIT Japan シングルスレッド? 16

Slide 17

Slide 17 text

©Project PLATEAU / MLIT Japan 調べてみると  ⚫ Javascriptは基本シングルスレッド、マルチスレッドにはできない (ウェブワーカー APIを使えばできるらしいが詳しいことは知らない) 17

Slide 18

Slide 18 text

©Project PLATEAU / MLIT Japan そもそも非同期処理の考え方が違うのでは ○ C/C++  ■ スレッドを並列させて処理速度を上げる ■ 同時並行で処理させる(ソケット通信とか、WEBサーバーとか) ○ Javascript ■ シングルスレッドだけど処理中のブロックを避けたい (ノンブロッキング) 18

Slide 19

Slide 19 text

©Project PLATEAU / MLIT Japan Javascript非同期処理 今昔物語 非同期処理を書くには3つのパターンがある。 1. コールバック関数を連ねる。 俗 にいう、コールバック 地 獄 に 陥 る 2. Promiseができたので  Promise  then thenで繋げる ECMAScript(ES2015 / ES6) 3. async await ができたのでスッキリ書ける。 ECMAScript(ES2017 / ES8) 19

Slide 20

Slide 20 text

©Project PLATEAU / MLIT Japan なるほど 20

Slide 21

Slide 21 text

©Project PLATEAU / MLIT Japan ? 21

Slide 22

Slide 22 text

©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

Slide 23

Slide 23 text

©Project PLATEAU / MLIT Japan 理解するには  理解するには内部を理解する必要があった ● コールスタック              後入れ先出し LIFO (Last-In-First-Out) ● タスクキュー(マクロタスクキュー) 先入れ先出し FIFO (First-In-First-Out) ● マイクロタスクキュー          先入れ先出し FIFO (First-In-First-Out) ● イベントループ 優先順位は以下 ● コールスタック=>実行 ● マイクロタスクキュー (コールスタックが空の場合)=>コールスタック=>実行 ● タスクキュー(コールスタックが空の場合)=>コールスタック=>実行   setTimeout関数などは指定した時間が経過したらコールバック関数をタスクキューに入れる  Promiseのコールバック関数は即座にマイクロタスクキューに関数を入れる 23

Slide 24

Slide 24 text

©Project PLATEAU / MLIT Japan タスクの動作  24

Slide 25

Slide 25 text

©Project PLATEAU / MLIT Japan 可視化ツールが存在したので実演 https://www.jsv9000.app/ 25

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

©Project PLATEAU / MLIT Japan 27

Slide 28

Slide 28 text

©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を利用(シングルスレッド)