Asynchronous Programming, Concurrency, and Parallelism
- 現実のプログラムの多くは非同期
-
非同期プログラムの実装
- マルチスレッド
- Java, C++など
- イベントループ
- JS (V8, SpiderMonkeyなどの処理系)
-
イベントループを採用することで、マルチスレッドプログラムの厄介ごとから開放される
- データ同期
- ミューテックス
- セマフォ
- etc.
-
JSをマルチスレッドで動作させるとしても、(mutableな)共有メモリを使うことはまれ
- 代わりにErlangのようなメッセージパッシングを行う
- 結論、JSの非同期プログラムは安全
-
非同期プログラムは一般に追うのが大変だが、TSを使えば楽になる
- 型
- async/awaitのネイティブサポート
- メッセージパッシングのプロトコル定義
JavaScript’s Event Loop
- メインスレッドは同期的に実行される
-
ネイティブのasynchronous APIが呼ばれると、制御は直ちにメインスレッドに戻る
- まるで何も実行しなかったかのように
- 「ネイティブのasynchronous API」の例
- XMLHttpRequest
- setTimeout
- readFile
- 自分でブラウザやNodeJSをフォークしない限りスクラッチで作ることはできない
- event queueにタスクが積まれる
- メインスレッドのコールスタックが空になり次第、イベントキューからタスクを取り出して実行する
- タスクの実行が完了し次第、メインスレッドに制御が戻る
- 以降、メインスレッドのコールスタックとイベントキュー両方が空になるまで繰り返し
setTimeout(()=>console.info('A'), 1)
setTimeout(()=>console.info('B'), 2)
console.info('C')
- 出力結果はC,A,B
-
流れ
- native timeout API実行 (1ms後にA表示)
- native timeout API実行 (2ms後にB表示)
- C表示
- 少なくとも1ms後、A表示のタスクがqueueに積まれる
- さらに1ms後、B表示のタスクがqueueに積まれる
- C表示後、イベントキューを見に行く
- A表示のタスクが積まれてあれば、A表示のタスクがqueueから取り出される
- A表示
- A表示後、イベントキューを見に行く
- B表示のタスクが積まれてあれば、B表示のタスクがqueueから取り出される
- B表示
- イベントキューもメインスレッドのコールスタックも空になった時点でプログラム終了
Working with Callbacks
- コールバック地獄の話
- 簡単な非同期タスクならどうぞ
Regaining Sanity with Promises
- Promiseモナドの話
async and await
- await: 言語レベルでの
.then
の糖衣
Async Streams
-
複数の値が、未来の複数の時点で有効になるようなケースではどうか?
- そう珍しいことではない
- ファイルシステムからの読み込み
- ビデオストリーミング
- キーストローク
- 投票
-
モデリング方法はいくつかある
- event emitter
- NodeJSのEventEmitter
- reactive programming
- RxJS, xstreamなど
- 両者の違いは、callbackとpromiseのようなもの
-
Observable
- reactive programmingの基本構成要素
- 2017にはObservableをECMA標準化しようという提案が為された
- https://github.com/tc39/proposal-observable
- が、2020時点でドラフトのまま
- 議事録リポジトリ: https://github.com/rwaldron/tc39-notes
Event Emitters
- ブラウザでいう
EventTarget
基底クラス的なやつ。略
Emitters in the Wild
- 文字列を型に変換するのはポピュラーなパターン
lib.dom.d.ts
の実装より抜粋
interface WindowEventMap extends GlobalEventHandlersEventMap, WindowEventHandlersEventMap {
"abort": UIEvent;
"afterprint": Event;
"beforeprint": Event;
"beforeunload": BeforeUnloadEvent;
// ...
}
...
/** A window containing a DOM document; the document property points to the DOM document loaded in that window. */
interface Window extends EventTarget, AnimationFrameProvider, GlobalEventHandlers, WindowConsole, WindowEventHandlers, WindowLocalStorage, WindowOrWorkerGlobalScope, WindowSessionStorage {
...
addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
-
footgun
- 自分の足を撃ち抜いてしまうような
-
endemic
- 風土の
- 文脈では、「(マルチスレッドの)分野の」くらいの意味か
-
reminiscent
- 思い出させる
-
ballot box
- 投票箱
-
Super Tuesday
- 3月第2火曜日
- アメリカ合衆国大統領選挙の予備選挙・党員集会が集中する