Cloud firestoreなどのサードパーティライブラリによって提供される非同期関数または監視対象を操作するwaitFor
場合、プロセスを待つ必要があるときに、以下に示すメソッド(TypeScriptですが、アイデアが得られます...)が役立つ関数を見つけました。完了する必要がありますが、コールバック内のコールバック内にコールバックを埋め込む必要はなく、無限ループのリスクもありません。
このメソッドはwhile (!condition)
スリープループに似ていますが、非同期で生成され、trueまたはタイムアウトになるまで定期的に完了条件のテストを実行します。
export const sleep = (ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
/**
* Wait until the condition tested in a function returns true, or until
* a timeout is exceeded.
* @param interval The frenequency with which the boolean function contained in condition is called.
* @param timeout The maximum time to allow for booleanFunction to return true
* @param booleanFunction: A completion function to evaluate after each interval. waitFor will return true as soon as the completion function returns true.
*/
export const waitFor = async function (interval: number, timeout: number,
booleanFunction: Function): Promise<boolean> {
let elapsed = 1;
if (booleanFunction()) return true;
while (elapsed < timeout) {
elapsed += interval;
await sleep(interval);
if (booleanFunction()) {
return true;
}
}
return false;
}
他のタスクを実行する前に、バックエンドで長時間実行されているプロセスを完了したいとします。たとえば、アカウントのリストを合計する関数があるが、計算する前にバックエンドからアカウントを更新したい場合は、次のようにすることができます。
async recalcAccountTotals() : number {
this.accountService.refresh(); //start the async process.
if (this.accounts.dirty) {
let updateResult = await waitFor(100,2000,()=> {return !(this.accounts.dirty)})
}
if(!updateResult) {
console.error("Account refresh timed out, recalc aborted");
return NaN;
}
return ... //calculate the account total.
}