Edited at

Async Functionでポーリングを書くとループになるので簡潔でよい

More than 1 year has passed since last update.

Async functionを使うとポーリングがループで書けて便利だったので共有します。

下記のようにサーバーサイドでバックグラウンド処理が完了したら次の画面に遷移する、というような状況で、waitって関数でポーリングすると想定してください。

startBackgroundProcessing();

wait().then(() => {
moveToNextScreen();
});

まずヘルパー関数を定義します。Promise版setTimeoutと、ポーリング先のAPIを叩く関数です。

const sleep = (n) => new Promise(resolve => setTimeout(resolve, n));

const isProcessing = async (id) => {
const {processed} = await new Promise((resolve, reject) => $.ajax({
type: 'GET',
url: '/api/v1/somewhere',
dataType : 'JSON',
success: resolve,
error: reject
}));

return !processed;
};

Async functionを使わない場合のwaitの実装例。継続渡しになって補助関数を定義しないといけないし、難しいです。

const waitWithContinuation = (id, cont) =>

sleep(POLLING_INTERVAL).then(() =>
isProcessing(id).then(processed => {
if (processed) {
cont();
} else {
waitWithContinuation(id, cont);
}
})
);

const wait = (id) => new Promise(resolve => waitWithContinuation(id, resolve));

Async functionを使う場合。簡潔に書けました。

const wait = async (id) => {

while (await isProcessing(id)) {
await sleep(POLLING_INTERVAL);
}
};

エラー処理は省略しています。