www.oreilly.com
Asynchronous Programming, Concurrency, and Parallelism
- 現実のプログラムの多くは非同期
- 非同期プログラムの実装
- イベントループを採用することで、マルチスレッドプログラムの厄介ごとから開放される
- JSをマルチスレッドで動作させるとしても、(mutableな)共有メモリを使うことはまれ
- 結論、JSの非同期プログラムは安全
- 非同期プログラムは一般に追うのが大変だが、TSを使えば楽になる
- 型
- async/awaitのネイティブサポート
- メッセージパッシングのプロトコル定義
- メインスレッドは同期的に実行される
- ネイティブのasynchronous APIが呼ばれると、制御は直ちにメインスレッドに戻る
- まるで何も実行しなかったかのように
- 「ネイティブのasynchronous API」の例
- 自分でブラウザや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
async and await
Async Streams
- 複数の値が、未来の複数の時点で有効になるようなケースではどうか?
- モデリング方法はいくつかある
- event emitter
- reactive programming
- 両者の違いは、callbackとpromiseのようなもの
- Observable
- reactive programmingの基本構成要素
- 2017にはObservableをECMA標準化しようという提案が為された
- が、2020時点でドラフトのまま
Event Emitters
- ブラウザでいう
EventTarget
基底クラス的なやつ。略
Emitters in the Wild
- 文字列を型に変換するのはポピュラーなパターン
lib.dom.d.ts
の実装より抜粋
interface WindowEventMap extends GlobalEventHandlersEventMap, WindowEventHandlersEventMap {
"abort": UIEvent;
"afterprint": Event;
"beforeprint": Event;
"beforeunload": BeforeUnloadEvent;
}
...
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