3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeScript(JavaScript)で複数の非同期関数を直列に実行したい

Last updated at Posted at 2021-07-05

複数の非同期関数を並列に実行する方法は簡単です。Promise.allを使うだけです。

/*
 * 1秒待機してからテキストをコンソール出力する非同期関数
 */
function asyncFunc(text: string) {
  return new Promise<void>((resolve) => {
    setTimeout(() => {
      console.log(text);
      resolve();
    }, 1000);
  });
}

(async function main() {
  console.log("start");
  const promises = ["1", "2", "3", "4", "5"].map((str) => asyncFunc(str));
  await Promise.all(promises); // 並列実行して全ての完了を待ち合わせる
  console.log("end");
})();

/* 実行結果 (1~5はほぼ同時に出力される)
start
1
2
3
4
5
end
*/

やりたいこと

では、全ての非同期関数を直列に実行するにはどうすればいいでしょうか。

結論から書いてしまうと以下です。

/*
 * 1秒待機してからテキストをコンソール出力する非同期関数
 */
function asyncFunc(text: string) {
  return new Promise<void>((resolve) => {
    setTimeout(() => {
      console.log(text);
      resolve();
    }, 1000);
  });
}

(async function main() {
  console.log("start");
  await ["1", "2", "3", "4", "5"].reduce(async (acc, cur) => {
    await acc;
    return asyncFunc(cur);
  }, Promise.resolve());
  console.log("end");
})();

/* 実行結果 (1~5は1秒毎に出力される)
start
1
2
3
4
5
end
*/

複数の非同期関数を直列に実行するAPIは用意されていないので、自分でreduceなどを使って書く必要があります。
大したコード量ではないですが、初心者としてはArray.reduceはとっつきにくいですし、並列実行のコードよりは見通しが悪いかもしれません。
そう思った場合、同期実行部分を以下のようにutility関数にしてしまうと多少見通しが良くなります。

/*
 * 1秒待機してからテキストをコンソール出力する非同期関数
 */
function asyncFunc(text: string) {
  return new Promise<void>((resolve) => {
    setTimeout(() => {
      console.log(text);
      resolve();
    }, 1000);
  });
}

/*
* 非同期関数の配列を渡すと直列実行するutility関数
*/
async function syncronize(asyncFuncs: Array<() => Promise<any>>){
  return asyncFuncs.reduce<Promise<any>>(async (acc, cur) => {
    await acc;
    return cur()
  }, Promise.resolve())   
}

(async function main() {
  console.log("start");
  const asuncFuncs = await ["1", "2", "3", "4", "5"].map((str) => () => asyncFunc(str));
  await syncronize(asuncFuncs); // 非同期関数の配列を直列に実行
  console.log("end");
})();

/* 実行結果 (1~5は1秒毎に出力される)
  start
  1
  2
  3
  4
  5
  end
  */

utilityに切り出したコード量は少ないですが、ややこしい部分を多少外に出すことができました。

tips程度の内容ですがググったら意外とHitしなかったので、誰かの助けになればという思いで記事にしておきます。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?