空雲リファレンス

[TypeScript/JavaScript] Promiseの終了を待たないawaitの利用方法

Promiseの終了を待たないawaitの利用方法

Promiseは不便?

Promiseで非同期のプログラムを組む際、対象のPromiseはresolveを呼び出して実行を完了しているのか、それともまだ実行中なのかを判断したいことがあります。しかし単純にawaitで状態を確認しようとしても、終了まで処理がブロックされてしまいます。また、thenの実行時にフラグを操作すれば状態を確認することは可能ですが、それなりに書き方が冗長になります。

「await時にまだ処理が終了していなければ、ブロックせずに実行中であることを識別できる値を返す」というのが可能なら話は簡単です。実はこれ、かなり簡単に書くことが出来ます。

ソースコード

const main = async () => { // ウエイト用 const sleep = (msec: number) => new Promise(resolve => setTimeout(resolve, msec)) // 1000ms後に終了するPromise const p = new Promise(resolve => setTimeout(() => resolve("end"), 1000)) while (true) { // pが終了していなければ即座にundefinedが返り、終了したらendが返る const result = await Promise.race([p, undefined]) console.log(result) if (result) break; // 100ms待つ await sleep(100); } } main()

実行結果

undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined end

実行確認用

https://www.typescriptlang.org/

解説

肝はPromise.raceです。私は時々使うのですが、一般的なところでは滅多にお目にかかることはありません。この関数は、渡した値の中から待ちが発生していない値を返します。また、複数の処理が終了している場合は、先頭側の値を優先して返します。

この性質を利用して、目的のPromiseの後ろに待つ必要の無い値を入れます。するとPromiseが終了するまでは、そちらの値が返ってくるのです。そしてPromiseが終了した時点で、今度はPromiseが返した値に変化します。

まとめ

Promise.allに比べると日の目を見ないPromise.raceですが、実はとても使えるヤツなので、忘れないであげてください。