Signatur
Beschreibung
Mit slice() wird ein Byte-Bereich eines SharedArrayBuffer in einen neuen, eigenständigen SharedArrayBuffer kopiert. Die Methode arbeitet genauso wie ArrayBuffer.prototype.slice(), liefert aber wieder einen gemeinsam nutzbaren Speicherbereich, den man per postMessage() an Worker weitergeben kann.
Wichtig: Das Ergebnis ist eine Kopie und keine Sicht auf denselben Speicher. Was später in den Originalpuffer geschrieben wird, taucht in der Kopie nicht auf, und umgekehrt genauso wenig. Brauchst du nur eine Sicht auf einen Teilbereich, ohne etwas zu kopieren, nimm stattdessen eine typisierte Array-Ansicht mit Offset, zum Beispiel new Int32Array(sab, byteOffset, length).
Negative Indizes zählen vom Ende des Puffers aus. Werte außerhalb des Bereichs werden auf 0 bis byteLength begrenzt. Ist end kleiner oder gleich start, entsteht ein leerer Puffer mit der Länge 0.
Ein typischer Anwendungsfall ist ein Schnappschuss eines gemeinsam genutzten Puffers, etwa um den aktuellen Stand eines Ringpuffers oder Zustandsspeichers unabhängig von weiteren Schreibvorgängen der Worker zu sichern.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $start | number | 0 | Byte-Index (nullbasiert), ab dem kopiert wird (inklusive). Negative Werte zählen vom Ende aus (byteLength + start). Nicht-numerische Werte werden in Ganzzahlen umgewandelt. |
| $end | number | byteLength | Byte-Index, vor dem das Kopieren endet (exklusiv). Negative Werte zählen vom Ende aus. Werte größer als byteLength werden auf byteLength begrenzt. |
Rückgabewert
SharedArrayBuffer mit den kopierten Bytes. Seine byteLength ist max(end - start, 0) (nach der Normalisierung der Indizes). Ist der Originalpuffer wachstumsfähig, ist die Kopie trotzdem nicht wachstumsfähig.Beispiele
Grundlegende Verwendung und negative Indizes
const sab = new SharedArrayBuffer(16);
const view = new Uint8Array(sab);
view.forEach((_, i) => { view[i] = i; });
const teil = sab.slice(4, 8);
console.log(teil.byteLength, [...new Uint8Array(teil)]);
// Letzte 3 Bytes
const ende = sab.slice(-3);
console.log([...new Uint8Array(ende)]);
// Leerer Bereich
console.log(sab.slice(10, 5).byteLength);
Kopie statt Sicht – Änderungen sind unabhängig
const sab = new SharedArrayBuffer(8);
const original = new Int32Array(sab);
original[0] = 42;
const kopie = new Int32Array(sab.slice(0, 4));
original[0] = 99; // Original ändern
console.log(kopie[0]); // bleibt 42
console.log(original[0]); // 99
console.log(kopie.buffer instanceof SharedArrayBuffer);
Konsistenter Schnappschuss eines Worker-Puffers (Node.js)
import { Worker } from 'node:worker_threads';
const sab = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
const zaehler = new Int32Array(sab);
const worker = new Worker(`
const { workerData } = require('node:worker_threads');
const z = new Int32Array(workerData);
for (let i = 0; i < 1000; i++) Atomics.add(z, 0, 1);
`, { eval: true, workerData: sab });
worker.on('exit', () => {
// Stand einfrieren, bevor weitere Schreibzugriffe passieren
const snapshot = new Int32Array(sab.slice(0));
console.log('Zählerstand:', snapshot[0]);
});
// Wichtig · Fallstricke
- Keine atomare Kopie:
slice()kopiert Byte für Byte ohne Synchronisation. Schreiben andere Worker gleichzeitig in den Puffer, kann der Schnappschuss uneinheitlich sein und zerrissene Werte enthalten. Sichere solche Zugriffe mitAtomics.wait()/Atomics.notify()oder einer eigenen Sperre ab. - Speicherverbrauch: Bei jedem Aufruf wird neuer Speicher belegt. Wenn du nur lesen willst, ist eine typisierte Array-Ansicht mit Offset (
new Uint8Array(sab, offset, len)) günstiger. - Wachstumsfähige Puffer: Auch wenn das Original mit
maxByteLengthangelegt wurde, ist das Ergebnis immer ein Puffer mit fester Länge. - Browser-Kompatibilität:
SharedArrayBuffergibt es nur in cross-origin isolated Kontexten. Die Seite muss dafür mit den HeadernCross-Origin-Opener-Policy: same-originundCross-Origin-Embedder-Policy: require-corpausgeliefert werden (prüfen mitcrossOriginIsolated). Diese Einschränkung ist eine Schutzmaßnahme gegen Spectre. In Node.js steht die Klasse ohne Einschränkung zur Verfügung. - Wird die Methode auf einem normalen
ArrayBufferaufgerufen, zum Beispiel übercall(), wirft sie einenTypeError.