INTEGRITY Dokumentace

Plánovač

Kontext

scheduler globální objekt poskytuje API pro plánování úloh založené na návrh WICG Scheduling APIs. Workers v současnosti implementují scheduler.wait() metoda.

scheduler.wait() vrací Promise, který se splní po zadaném počtu milisekund. Jde o await-ovatelná alternativa k setTimeout() která nevyžaduje callback.

Stejně jako jiné časovače ve Workers, scheduler.wait() se při nasazení na Cloudflare během provádění CPU neposouvá. Jedná se o bezpečnostní opatření ke zmírnění útoků Spectre. Při lokálním vývoji časovače postupují bez ohledu na to, zda dochází k I/O operacím.

Syntaxe

await scheduler.wait(delay);
await scheduler.wait(delay, options);

Parametry

Návratová hodnota

A Promise<void> který se vyřeší po delay milisekund. Pokud AbortSignal je zadán a přerušen před uplynutím zpoždění, Promise je odmítnut s AbortError.

Příklady

Základní zpoždění

Použijte scheduler.wait() pro pozastavení provádění na určenou dobu.

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;

Opakovat s exponenciálním prodlením

Použijte scheduler.wait() k implementaci prodlevy mezi jednotlivými pokusy o opakování. Tento příklad používá exponenciální odklad s jitterem.

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;

Zrušení pomocí AbortSignal

Použijte AbortController pro zrušení probíhajícího čekání.

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;