demo · v132
Which Body method should I use?
Body has six ways to drain. .bytes() is the new one, and it's the right default for binary data. Here's the cheat sheet, plus recipes for the common cases.
method matrix
| method | returns | copies / wraps | typical use |
|---|---|---|---|
.text() | string | UTF-8 decode | HTML, JSON, CSS |
.json() | parsed JS value | decode + parse | JSON responses |
.blob() | Blob | wraps | images, video, downloads |
.formData() | FormData | multipart parse | form posts |
.arrayBuffer() | ArrayBuffer | raw bytes (typed-array wrap needed) | WebAssembly, ZIP, parsing |
.bytes() v132 | Uint8Array | raw bytes (already a view) | same as arrayBuffer() but one fewer line |
recipes
upload a Uint8Array
Build the payload in JS (WebAssembly memory, image manipulation) and POST it.
const view = new Uint8Array(2048);
crypto.getRandomValues(view);
await fetch("/upload", {
method: "POST",
body: view
});
// inside the server handler:
// const view = await request.bytes(); // v132+
// process(view);
decode an image header
Read the first 8 bytes of a PNG without ever materialising the entire image.
const res = await fetch("/icon.png");
const view = await res.bytes();
const sig = view.subarray(0, 8);
const isPNG = sig[0] === 0x89 && sig[1] === 0x50;
stream + bytes()
For large responses, pipe the body and use bytes() on each chunk's Response view.
const reader = res.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// value is already Uint8Array
process(value);
}
service worker rewrite
Intercept a request, swap a few bytes, re-emit. Was awkward with arrayBuffer; one line shorter now.
self.addEventListener("fetch", (e) => {
e.respondWith((async () => {
const r = await fetch(e.request);
const v = await r.bytes();
v[0] = 0x42; // rewrite first byte
return new Response(v, r);
})());
});