HTTP server: Streaming
An example HTTP server that streams a response back to the client.
function handler(_req: Request): Response {Set up a variable to store a timer ID, and the ReadableStream.
let timer: ReturnType<typeof setInterval> | undefined = undefined;
const body = new ReadableStream({When the stream is first created, start an interval that will emit a chunk every second containing the current time.
start(controller) {
timer = setInterval(() => {
const message = `It is ${new Date().toISOString()}\n`;
controller.enqueue(new TextEncoder().encode(message));
}, 1000);
},If the stream is closed (the client disconnects), cancel the interval.
cancel() {
if (timer !== undefined) {
clearInterval(timer);
}
},
});Return a response with the stream as the body.
return new Response(body, {
headers: {
"content-type": "text/plain",
"x-content-type-options": "nosniff",
},
});
}An async generator is often a more natural producer. ReadableStream.from turns any async iterable into a stream usable as a Response body.
async function* ticks(): AsyncGenerator<Uint8Array> {
const encoder = new TextEncoder();
for (let i = 1; i <= 3; i++) {
yield encoder.encode(`tick ${i}\n`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
function iteratorHandler(_req: Request): Response {
return new Response(ReadableStream.from(ticks()), {
headers: { "content-type": "text/plain" },
});
}Serve the interval stream on / and the generator stream on /ticks.
Deno.serve((req) =>
new URL(req.url).pathname === "/ticks" ? iteratorHandler(req) : handler(req)
);Run this example locally using the Deno CLI:
deno run -N https://docs.deno.com/examples/scripts/http_server_streaming.tsTry this example in a Deno Deploy playground