LoginSignup
8
4

More than 1 year has passed since last update.

javascriptのawaitにタイムアウトを設定したい

Last updated at Posted at 2022-10-13

通常の await

// ただ1秒待つだけの関数
async function sleepOneSec() {
  await new Promise((resolve) => setTimeout(resolve, 1000));
}

async function main() {
  await sleepOneSec();
}

// 実行
main();

await with timeout

/**
 * await にタイムアウトを設定する
 *
 * timeoutを超えて await で待機すると UnhandledPromiseRejection 例外が throw されます。
 * @param {Promise} promise - 実行したい promise 関数
 * @param {number} timeout - タイムアウト(ms)
 * @returns Promise<T>
 */
export function withTimeout<T>(promise: Promise<T>, timeout: number) {
  const errorMessage = `await での待機が ${timeout}ms を超えました`;

  const timeoutPromise: Promise<T> = new Promise((_, reject) =>
    setTimeout(() => reject(errorMessage), timeout),
  );
  // Promise.race()を利用して先に解決した方を優先する
  return Promise.race([
    promise, // 本来実行したい promise 関数
    timeoutPromise, // こちらの方が早く解決すると reject()
  ]);
}

// ただ1秒待つだけの関数
async function sleepOneSec() {
  await new Promise((resolve) => setTimeout(resolve, 1000));
}

async function main() {
  // OK (タイムアウト2秒)
  await withTimeout(sleepOneSec(), 2000);

  // NG (タイムアウト0.5秒)
  await withTimeout(sleepOneSec(), 500);
  /*
  [ERROR] 19:45:13 UnhandledPromiseRejection:
    This error originated either by throwing inside of an async function without a catch block,
      or by rejecting a promise which was not handled with .catch().
    The promise rejected with the reason "await での待機が 500ms を超えました".
  */
}

// 実行
main();

await で長時間待ちたくない時によいな…と思ってたのですが await-timeout なるものが既にありました。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4