scheduler グローバルは、WICG Scheduling APIs の提案 ↗ に基づくタスクスケジューリング API を提供します。Workers は現在、scheduler.wait() メソッドを実装しています。
scheduler.wait() は、指定したミリ秒のあとで解決する Promise を返します。コールバックが不要な、setTimeout() の await 可能な代替です。
Workers のほかの タイマー と同様、Cloudflare へデプロイしたあと、scheduler.wait() は CPU 実行中には進みません。これは Spectre 攻撃を緩和するためのセキュリティ対策 です。ローカル開発では、I/O の有無にかかわらずタイマーは進みます。
await scheduler.wait(delay);
await scheduler.wait(delay, options);-
delaynumber- 返した Promise が解決するまでの待ち時間(ミリ秒)です。
-
optionsobject optional-
wait 操作の省略可能な設定です。
-
signalAbortSignal optional- wait をキャンセルする
AbortSignalです。シグナルが abort されると、返した Promise はAbortErrorで reject されます。
- wait をキャンセルする
-
delay ミリ秒後に解決する Promise<void> です。AbortSignal が渡され、遅延が終わる前に abort された場合、Promise は AbortError で reject されます。
scheduler.wait() で、指定した時間だけ実行を一時停止します。
export default {
async fetch(request) {
// Wait for 1 second
await scheduler.wait(1000);
return new Response("Delayed response");
},
};export default {
async fetch(request): Promise<Response> {
// Wait for 1 second
await scheduler.wait(1000);
return new Response("Delayed response");
},
} satisfies ExportedHandler;scheduler.wait() で、再試行のあいだに遅延を入れます。この例は、ジッター付きの指数バックオフを使います。
async function fetchWithRetry(url, maxAttempts = 3) {
const baseBackoffMs = 100;
const maxBackoffMs = 10000;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fetch(url);
} catch (err) {
if (attempt + 1 >= maxAttempts) {
throw err;
}
const backoffMs = Math.min(
maxBackoffMs,
baseBackoffMs * Math.random() * Math.pow(2, attempt),
);
await scheduler.wait(backoffMs);
}
}
throw new Error("unreachable");
}
export default {
async fetch(request) {
const response = await fetchWithRetry("https://example.com/api");
return new Response(response.body, response);
},
};async function fetchWithRetry(url: string, maxAttempts = 3): Promise<Response> {
const baseBackoffMs = 100;
const maxBackoffMs = 10000;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fetch(url);
} catch (err) {
if (attempt + 1 >= maxAttempts) {
throw err;
}
const backoffMs = Math.min(
maxBackoffMs,
baseBackoffMs * Math.random() * Math.pow(2, attempt),
);
await scheduler.wait(backoffMs);
}
}
throw new Error("unreachable");
}
export default {
async fetch(request): Promise<Response> {
const response = await fetchWithRetry("https://example.com/api");
return new Response(response.body, response);
},
} satisfies ExportedHandler;AbortController で、待機中の wait をキャンセルします。
export default {
async fetch(request) {
const controller = new AbortController();
// Cancel the wait after 500ms
setTimeout(() => controller.abort(), 500);
try {
await scheduler.wait(5000, { signal: controller.signal });
return new Response("Wait completed");
} catch (err) {
if (err instanceof DOMException && err.name === "AbortError") {
return new Response("Wait was cancelled", { status: 408 });
}
throw err;
}
},
};export default {
async fetch(request): Promise<Response> {
const controller = new AbortController();
// Cancel the wait after 500ms
setTimeout(() => controller.abort(), 500);
try {
await scheduler.wait(5000, { signal: controller.signal });
return new Response("Wait completed");
} catch (err) {
if (err instanceof DOMException && err.name === "AbortError") {
return new Response("Wait was cancelled", { status: 408 });
}
throw err;
}
},
} satisfies ExportedHandler;- タイマー —
setTimeout()とsetInterval()の API - パフォーマンスとタイマー —
performance.now()とタイマーのセキュリティ動作 - AbortController と AbortSignal — 非同期操作のキャンセル
- WICG Scheduling APIs の提案 ↗ — この API の元になる仕様