Signatur
Beschreibung
Response.clone() erzeugt ein neues Response-Objekt mit denselben Werten für Status, Header, URL, Typ und Body wie das Original. Der wichtigste Punkt ist, dass der Body ein ReadableStream ist und nur einmal gelesen werden kann. Nach json(), text(), blob() und ähnlichen Methoden gilt der Body als verbraucht (bodyUsed === true). Mit clone() lässt sich derselbe Inhalt trotzdem mehrfach auslesen.
Intern wird der Body-Stream mit einem Mechanismus wie ReadableStream.tee() in zwei Zweige aufgeteilt. Original und Kopie lassen sich danach unabhängig voneinander lesen.
Typische Einsatzfälle sind:
- Service Worker: Eine Antwort wird gleichzeitig in den
Cachegelegt und an die Seite zurückgegeben. - Logging oder Fehlerdiagnose: Der Body wird zusätzlich als Text gelesen, während der normale Code ihn als JSON auswertet.
- Middleware oder Interceptors: Eine Antwort wird geprüft, bevor sie unverändert weitergereicht wird.
Rufen Sie clone() vor dem ersten Lesen des Bodys auf. Ist der Body bereits verbraucht, wirft die Methode einen TypeError.
Rückgabewert
Response-Objekt mit denselben Eigenschaften (status, statusText, headers, url, type) und einem eigenen, unabhängig lesbaren Body.Beispiele
Body zweimal lesen: als JSON und als Rohtext
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
// Kopie VOR dem ersten Lesen anlegen
const kopie = response.clone();
const daten = await response.json();
const rohtext = await kopie.text();
console.log(daten.id);
console.log(rohtext.length > 0);
console.log(response.bodyUsed, kopie.bodyUsed);
Service Worker: Antwort cachen und gleichzeitig ausliefern
// sw.js
self.addEventListener('fetch', (event) => {
event.respondWith((async () => {
const cache = await caches.open('v1');
const cached = await cache.match(event.request);
if (cached) return cached;
const response = await fetch(event.request);
if (response.ok) {
// Eine Kopie für den Cache, das Original für die Seite
await cache.put(event.request, response.clone());
}
return response;
})());
});
Fehlerdiagnose: JSON-Parse-Fehler mit Rohtext protokollieren
const ladeJson = async (url) => {
const response = await fetch(url);
const sicherung = response.clone();
try {
return await response.json();
} catch (err) {
const text = await sicherung.text();
console.error('Ungültiges JSON von', url, '→', text.slice(0, 100));
throw err;
}
};
await ladeJson('/api/kaputt').catch(() => {});
Fehler bei verbrauchtem Body
const response = new Response('Hallo Welt');
await response.text();
try {
response.clone();
} catch (err) {
console.log(err.name);
}
// Wichtig · Fallstricke
- Reihenfolge beachten:
clone()muss aufgerufen werden, bevor der Body gelesen wird. BeibodyUsed === truewirft die Methode einenTypeError. - Speicher und Gegendruck: Durch das Aufteilen des Streams werden die Daten zwischengespeichert, bis beide Zweige gelesen sind. Wird eine Kopie nie gelesen, puffert der Browser unter Umständen den gesamten Body im Speicher. Das ist bei großen Downloads problematisch, und das Lesen des anderen Zweigs kann dabei stocken. Lesen Sie deshalb alle Kopien oder brechen Sie sie mit
body.cancel()ab. - Keine tiefe Unabhängigkeit bei opaken Antworten: Auch Antworten mit
type === 'opaque'(ausno-cors-Anfragen) lassen sich klonen. Ihr Inhalt bleibt jedoch unlesbar. - Ein
Responseohne Body (z. B.body === nullbei Status 204) lässt sich problemlos klonen. - Für
Request-Objekte gibt es das GegenstückRequest.prototype.clone()mit denselben Regeln. - Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt, auch in Web Workern und Service Workern. In Node.js ist sie ab Version 18 über das globale
fetch(undici) verfügbar.