Start · Sprachen · JavaScript · Referenz · RTCDataChannel.bufferedAmount

RTCDataChannel.bufferedAmount

Eigenschaft

Gibt die Anzahl der Bytes zurück, die über <code>send()</code> eingereiht, aber noch nicht über den Datenkanal übertragen wurden (schreibgeschützt).

seit JavaScript Baseline: alle modernen Browser (Chrome, Firefox, Kategorie: webapi

Signatur

RTCDataChannel.bufferedAmount

Beschreibung

Die schreibgeschützte Eigenschaft bufferedAmount eines RTCDataChannel gibt an, wie viele Bytes an Anwendungsdaten derzeit in der Sendewarteschlange liegen. Jeder Aufruf von send() erhöht den Wert um die Größe der Nachricht. Sobald der Browser die Daten an die darunterliegende Transportschicht (SCTP) übergeben hat, sinkt der Wert wieder. Der Overhead von Protokoll und Framing wird dabei nicht mitgezählt.

Die Eigenschaft ist vor allem für die Flusskontrolle (Backpressure) wichtig. Wer große Dateien oder Datenströme in vielen Teilstücken (Chunks) verschickt, sollte nicht einfach in einer Schleife send() aufrufen. Sonst wächst der interne Puffer unkontrolliert, der Speicherverbrauch steigt stark, und manche Browser schließen den Kanal sogar, wenn der Puffer überläuft. Besser prüft man vor jedem Senden bufferedAmount und pausiert, sobald ein Schwellwert überschritten ist.

Zusammen mit bufferedAmountLowThreshold und dem Ereignis bufferedamountlow lässt sich das ereignisgesteuert umsetzen: Sobald bufferedAmount auf den Schwellwert oder darunter fällt, feuert das Ereignis, und die Anwendung kann weitersenden.

Wird der Kanal geschlossen, setzt der Browser den Wert nicht auf 0 zurück. Er zeigt dann weiterhin die Bytes an, die zum Zeitpunkt des Schließens noch nicht gesendet waren.

Rückgabewert

Typ
number
Beschreibung
Eine nicht-negative Ganzzahl: die Anzahl der Bytes, die noch in der Sendewarteschlange des Kanals liegen.

Beispiele

Füllstand des Sendepuffers abfragen

const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('chat');

channel.addEventListener('open', () => {
  channel.send('Hallo Welt!');
  channel.send(new Uint8Array(1024));
  console.log(`Im Puffer: ${channel.bufferedAmount} Bytes`);
});
Im Puffer: 1035 Bytes (Wert hängt vom Sendefortschritt ab)

Große Datei mit Flusskontrolle senden

const CHUNK_SIZE = 16 * 1024;          // 16 KiB pro Nachricht
const HIGH_WATER = 1024 * 1024;        // ab 1 MiB pausieren
const LOW_WATER = 256 * 1024;          // ab 256 KiB weitersenden

const sendFile = async (channel, file) => {
  const buffer = await file.arrayBuffer();
  channel.bufferedAmountLowThreshold = LOW_WATER;
  let offset = 0;

  const pump = () => {
    while (offset < buffer.byteLength) {
      if (channel.bufferedAmount > HIGH_WATER) {
        // Warten, bis der Puffer wieder leerer ist
        channel.addEventListener('bufferedamountlow', pump, { once: true });
        return;
      }
      channel.send(buffer.slice(offset, offset + CHUNK_SIZE));
      offset += CHUNK_SIZE;
    }
    console.log('Alle Chunks eingereiht');
  };

  pump();
};

// Verwendung: sendFile(channel, fileInput.files[0]);
Alle Chunks eingereiht

Vor dem Schließen warten, bis der Puffer leer ist

const closeWhenDrained = (channel) =>
  new Promise((resolve) => {
    if (channel.bufferedAmount === 0) {
      channel.close();
      return resolve();
    }
    channel.bufferedAmountLowThreshold = 0;
    channel.onbufferedamountlow = () => {
      channel.onbufferedamountlow = null;
      channel.close();
      resolve();
    };
  });

// await closeWhenDrained(channel);
// console.log('Kanal sauber geschlossen');
Kanal sauber geschlossen

// Wichtig · Fallstricke

  • Eine Null bedeutet nicht, dass die Daten angekommen sind: Bei 0 hat der Browser die Daten nur an SCTP übergeben. Ob der Empfänger sie erhalten hat, sagt der Wert nicht. Dafür braucht es eine eigene Empfangsbestätigung auf Anwendungsebene.
  • Pufferüberlauf: Ältere Chrome-Versionen haben den Kanal geschlossen, sobald etwa 16 MiB im Puffer lagen. Große Datenmengen sollten deshalb immer mit Flusskontrolle gesendet werden. Die Nachrichtengröße sollte bei höchstens 16 bis 64 KiB liegen, damit die Übertragung zwischen verschiedenen Browsern funktioniert.
  • Nach dem Schließen: Im Zustand closing oder closed wird der Wert nicht zurückgesetzt, er steigt aber auch nicht mehr. Ein send() im Zustand closed löst einen InvalidStateError aus.
  • Zeichenketten: Gezählt werden die UTF-8-Bytes, nicht die Zeichen. 'ä' zählt also als 2 Bytes.
  • Kein Polling: Statt den Wert mit setInterval regelmäßig abzufragen, ist das Ereignis bufferedamountlow effizienter.
  • Die Eigenschaft wird in allen aktuellen Browsern unterstützt. In Node.js gibt es sie nur über Bibliotheken wie node-datachannel oder wrtc.