Start · Sprachen · JavaScript · Referenz · Response.clone()

Response.clone()

Methode

Erstellt eine unabhängige Kopie eines <code>Response</code>-Objekts, deren Body separat gelesen werden kann.

seit JavaScript Baseline: alle modernen Browser, Node.js 18+ (glob Kategorie: webapi

Signatur

Response.prototype.clone()

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 Cache gelegt 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

Typ
Response
Beschreibung
Ein neues 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);
1 true true true

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(() => {});
Ungültiges JSON von /api/kaputt → <!DOCTYPE html>...

Fehler bei verbrauchtem Body

const response = new Response('Hallo Welt');
await response.text();

try {
  response.clone();
} catch (err) {
  console.log(err.name);
}
TypeError

// Wichtig · Fallstricke

  • Reihenfolge beachten: clone() muss aufgerufen werden, bevor der Body gelesen wird. Bei bodyUsed === true wirft die Methode einen TypeError.
  • 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' (aus no-cors-Anfragen) lassen sich klonen. Ihr Inhalt bleibt jedoch unlesbar.
  • Ein Response ohne Body (z. B. body === null bei Status 204) lässt sich problemlos klonen.
  • Für Request-Objekte gibt es das Gegenstück Request.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.