Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

Scheduler

最終更新 Markdown で表示Agent セットアップ

背景

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);

パラメーター

  • delay number

    • 返した Promise が解決するまでの待ち時間(ミリ秒)です。
  • options object optional

    • wait 操作の省略可能な設定です。

    • signal AbortSignal optional

      • wait をキャンセルする AbortSignal です。シグナルが abort されると、返した Promise は AbortError で reject されます。

戻り値

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;

AbortSignal でキャンセルする

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;

関連リソース

役に立ちましたか?