勉強日記

チラ裏

Programming TypeScript ch8 Asynchronous Programming, Concurrency, and Parallelism (1/2)

www.oreilly.com


Asynchronous Programming, Concurrency, and Parallelism

  • 現実のプログラムの多くは非同期
  • 非同期プログラムの実装
    • マルチスレッド
    • イベントループ
  • イベントループを採用することで、マルチスレッドプログラムの厄介ごとから開放される
  • JSをマルチスレッドで動作させるとしても、(mutableな)共有メモリを使うことはまれ
    • 代わりにErlangのようなメッセージパッシングを行う
  • 結論、JSの非同期プログラムは安全
  • 非同期プログラムは一般に追うのが大変だが、TSを使えば楽になる
    • async/awaitのネイティブサポート
    • メッセージパッシングのプロトコル定義

JavaScript's Event Loop

  • メインスレッドは同期的に実行される
  • ネイティブのasynchronous APIが呼ばれると、制御は直ちにメインスレッドに戻る
    • まるで何も実行しなかったかのように
    • 「ネイティブのasynchronous API」の例
    • 自分でブラウザやNodeJSをフォークしない限りスクラッチで作ることはできない
  • event queueにタスクが積まれる
  • メインスレッドのコールスタックが空になり次第、イベントキューからタスクを取り出して実行する
  • タスクの実行が完了し次第、メインスレッドに制御が戻る
  • 以降、メインスレッドのコールスタックとイベントキュー両方が空になるまで繰り返し
setTimeout(()=>console.info('A'), 1)
setTimeout(()=>console.info('B'), 2)
console.info('C')
  • 出力結果はC,A,B
  • 流れ
    1. native timeout API実行 (1ms後にA表示)
    2. native timeout API実行 (2ms後にB表示)
    3. C表示
    4. 少なくとも1ms後、A表示のタスクがqueueに積まれる
    5. さらに1ms後、B表示のタスクがqueueに積まれる
    6. C表示後、イベントキューを見に行く
    7. A表示のタスクが積まれてあれば、A表示のタスクがqueueから取り出される
    8. A表示
    9. A表示後、イベントキューを見に行く
    10. B表示のタスクが積まれてあれば、B表示のタスクがqueueから取り出される
    11. B表示
    12. イベントキューもメインスレッドのコールスタックも空になった時点でプログラム終了

Working with Callbacks

  • コールバック地獄の話
  • 簡単な非同期タスクならどうぞ

Regaining Sanity with Promises

async and await

  • await: 言語レベルでの.thenの糖衣

Async Streams

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