Egy nagy JSON-fájl vagy a böngészőben keletkező mérési adat elküldésekor a fetch() törzse nem feltétlenül egy kész Blob vagy string. Adható neki ReadableStream is, így a kliens a keletkező bájtokat fokozatosan küldi. A lehetőség érdekes, de a duplex: "half" név könnyen félrevezet: nem kapunk vele HTTP-alapú WebSocketet.

A kérés már küldés közben él
A stream producer és fogyasztó közötti szerződés: a producer Uint8Array darabokat tesz a sorba, a fogyasztó pedig akkor kér többet, amikor tudja kezelni. A Fetch specifikáció a request body-t is ilyen streamként kezeli. Ez akkor hasznos, ha nem akarunk teljes fájlt vagy hosszú ideig gyűlő adatot memóriában tartani: kliensoldali feldolgozás után azonnal indulhat az átadás.
A minimális böngészős példa szándékosan lassú. Éles alkalmazásban a lines helyére kerülhet CSV-generátor, MediaRecorderből érkező adat vagy egy transzformált fájlfolyam.
const encoder = new TextEncoder();
const lines = ["első rekord\n", "második rekord\n", "harmadik rekord\n"];
const body = new ReadableStream({
async start(controller) {
for (const line of lines) {
controller.enqueue(encoder.encode(line));
await new Promise((resolve) => setTimeout(resolve, 250));
}
controller.close();
},
});
const response = await fetch("/api/import", {
method: "POST",
headers: { "Content-Type": "text/plain;charset=utf-8" },
body,
duplex: "half",
});
A duplex opció nem dísz: stream törzsnél a Fetch implementációk ezt kérik, jelenleg egyetlen megengedett értéke a "half". Az MDN leírása szerint ez azt jelenti, hogy a böngésző a válasz feldolgozása előtt elküldi a teljes kérést. Maga a Request.duplex property ráadásul nincs minden implementációban olvasható formában kivezetve; a beállítását nem érdemes feature detectálni.
A szerver dolgozhat, a kliens még vár
A fél duplex nem azt jelenti, hogy a szervernek a feltöltés végéig tétlenül kell állnia. A szerver már az első chunkok megérkezésekor írhat fájlba, ellenőrizhet rekordokat vagy elindíthat feldolgozást. A korlát a böngésző és a válasz közé kerül: az előbbi fetch() hívás promise-a nem válik a folyam közben használható válasszá. Vagyis nem építhetünk rá kétirányú, egy kapcsolaton futó interaktív protokollt.
Ez különbség a response streamekhez képest. Egy nagy letöltés response.body-ját régóta fogyaszthatjuk fokozatosan; a request stream ennek a feltöltési oldali megfelelője, de kisebb mozgástérrel. Ha a szervernek futás közben állapotot kell visszajeleznie, két kérés praktikusabb: egy streamelt POST és egy külön SSE-, polling- vagy WebSocket-csatorna.
Éles környezetben a hálózati útvonal a feltétel
A request streaming nem általános „feltöltés gyorsító”. A támogatást külön ellenőrizni kell: az MDN a duplex-et továbbra is kísérleti technológiaként jelöli. A Chromium saját dokumentációja szerint a streamelt request CORS-os kérésnél mindig preflightot vált ki, a no-cors mód nem használható, és az ott leírt implementáció HTTP/1.x kapcsolaton elutasítja a kérést. Ezért a helyi Node-demó vagy egy közvetlen HTTP/2 origin még nem bizonyítja, hogy a CDN, reverse proxy és böngésző teljes lánca is alkalmas.
Redirectnél is könnyű meglepetésbe futni. A streamet nem lehet egyszerűen újraolvasni és elküldeni a következő címre. A Chromium útmutatója szerint a 303 kivételével a redirectes streaming fetch hibával végződik. Feltöltési végpontot ezért végleges HTTPS URL-re érdemes tenni, és nem login- vagy régióátirányítás mögé.
Mikor érdemes elővenni?
Jó jelölt a kliensoldalról generált, hosszú export, ahol az adat minden darabja önállóan értelmezhető, vagy olyan import, amelyet a szerver soronként tud feldolgozni. Nem jó jelölt a hagyományos fájlfeltöltő, ha a kompatibilitás fontosabb a memóriaoptimalizálásnál: a FormData és a megszokott multipart feltöltés sokkal egyszerűbb fallbacket ad.
A stream nem helyettesíti a feltöltési korlátokat sem. A szervernek ugyanúgy maximális bájtméretet, időkorlátot és hitelesítést kell érvényesítenie; a végtelen vagy nagyon lassú producer egyébként sokáig foglalhat kapcsolatot. Hiba esetén a kliens oldali ReadableStream producerét is le kell állítani, különben feleslegesen folytathatja a CPU- vagy I/O-munkát akkor is, amikor a hálózati kérés már meghiúsult.
A gyakorlati ellenőrzőlista rövid: legyen valódi streaminget fogadó szerveroldal, legyen a feldolgozás idempotens, mérjük meg a proxykon átmenő kérést is, és tervezzünk visszaesést normál feltöltésre. A ReadableStream ekkor nem egy látványos API-trükk, hanem memóriahatár és adatátviteli késleltetés feletti kontroll.