中安拓也のブログ

プログラミングについて書くブログ。 Twitterやってます @l08084

【TypeScript】非同期コールバック関数にasync/awaitを利用する

はじめに

非同期型のコールバック関数(Callback function)にasync/awaitを利用する方法について説明します。使用言語はTypeScriptです。

コールバック関数のままだと困ること

async/awaitを利用しない非同期型のコールバック関数(この例の場合、setTimeout())だと、下記の例のように非同期型のコールバック関数内部の値("成功")を取得して、関数(getStatus())の戻り値として返すことができません。

  /**
   * ステータス(成功/失敗)を返す
   *
   * @private
   * @returns {string} ステータス
   * @memberof Tab1Page
   */
  private getStatus(): string {
    let status = "失敗";
    setTimeout(() => {
      status = "成功";
    }, 1000);
    return status; // 非同期処理のため、"成功"がセットされる前に"失敗"がreturnされてしまう
  }

  /**
   * getStatus()を呼び出して、
   * ステータスを取得する
   *
   * @private
   * @memberof Tab1Page
   */
  private retrieveStatus(): void {
    console.log(this.getStatus()); // "失敗"
  }

コールバック関数をasync/awaitに変換する

下記の例のようにasync/awaitを利用すると非同期型のコールバック関数の中身("成功")を取得して、関数(getStatus())の戻り値として返すことができます。

  /**
   * ステータス(成功/失敗)を返す
   *
   * @private
   * @returns {Promise<string>} ステータス
   * @memberof Tab1Page
   */
  private getStatus(): Promise<string> {
    return new Promise<string>((resolve, _) => {
      let status = "失敗";
      setTimeout(() => {
        status = "成功";
        resolve(status);
      }, 1000);
    });
  }

  /**
   * getStatus()を呼び出して、
   * ステータスを取得する
   *
   * @private
   * @returns {Promise<void>}
   * @memberof Tab1Page
   */
  private async retrieveStatus(): Promise<void> {
    console.log(await this.getStatus()); // "成功"
  }

参考サイト

Callback function (コールバック関数) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN