ArrayBuffer i TypeScript
Denne artikkelen forklarer ArrayBuffer i TypeScript.
Vi forklarer ArrayBuffer i TypeScript trinn for trinn, fra grunnleggende til praktiske teknikker.
YouTube Video
ArrayBuffer i TypeScript
ArrayBuffer er et innebygd objekt som representerer et «rått minneområde» for binærdata. Den representerer en råbuffer med fast lengde, hvor TypedArray eller DataView legges over for lesing og skriving.
Grunnleggende konsepter og egenskaper for ArrayBuffer
ArrayBuffer er en byte-sekvens med fast lengde. Du angir størrelsen i byte når du oppretter den, og lengden kan ikke endres senere.
1// Create a new ArrayBuffer of 16 bytes.
2const buf = new ArrayBuffer(16);
3console.log(buf.byteLength); // 16
- Denne koden oppretter en tom buffer på 16 byte. Du kan sjekke størrelsen ved å bruke
byteLength.
TypedArray og DataView — visninger for å manipulere buffere
ArrayBuffer har ikke mulighet til å lese eller skrive data. Derfor utføres faktiske operasjoner gjennom TypedArray eller DataView, hvor man spesifiserer typer som heltall eller flyttall og endianness ved tilgang til data.
1// Create a buffer and a Uint8Array view over it. Then write bytes and read them.
2const buffer = new ArrayBuffer(8);
3const u8 = new Uint8Array(buffer);
4
5u8[0] = 0x41; // 'A'
6u8[1] = 0x42; // 'B'
7console.log(u8); // Uint8Array(8) [ 65, 66, 0, 0, 0, 0, 0, 0 ]
Uint8Arrayer en byte-vis arrayvisning, og kan nås som et vanlig array. Hvis du legger flere visninger på sammeArrayBuffer, deler de det samme minnet for lesing og skriving.
DataView: Lesing og skriving ved vilkårlige grenser og endianness
DataView er nyttig for detaljert lesing og skriving per byte, og du kan spesifisere liten eller stor endian.
1// Using DataView to write/read multi-byte values with endianness control.
2const buf2 = new ArrayBuffer(8);
3const view = new DataView(buf2);
4
5// Write a 32-bit integer (little-endian)
6view.setInt32(0, 0x12345678, true);
7
8// Read it back as little-endian and big-endian
9const little = view.getInt32(0, true);
10const big = view.getInt32(0, false);
11console.log(little.toString(16)); // "12345678"
12console.log(big.toString(16)); // "78563412"
DataViewlar deg lese og skrive verdier ved å spesifisere offset i minnet, noe som gjør det egnet for implementering av protokoller som krever håndtering av nettverks-byterekkefølge.
Konvertering mellom strenger og ArrayBuffer (TextEncoder / TextDecoder)
For å konvertere tekst til binær og omvendt, bruk TextEncoder og TextDecoder.
1// Convert string -> ArrayBuffer and back using TextEncoder/TextDecoder.
2const encoder = new TextEncoder();
3const decoder = new TextDecoder();
4
5// Unicode escape sequences
6const str = "\u3053\u3093\u306B\u3061\u306F";
7const encoded = encoder.encode(str); // Uint8Array
8console.log(encoded); // Uint8Array([...])
9
10// If you need an ArrayBuffer specifically:
11const ab = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
12console.log(ab.byteLength); // bytes length of encoded text
13
14// Decode back
15const decoded = decoder.decode(encoded);
16console.log(decoded);TextEncoder.encodereturnerer enUint8Array, så dersom du trenger enArrayBuffer, bør du referere til dens.buffer-egenskap. Medslice-metoden kan du trekke ut nødvendig data ved å spesifisere offset og lengde.
Slicing og kopiering av ArrayBuffer
slice-metoden returnerer en ny ArrayBuffer. ArrayBuffer kan ikke endres i størrelse; hvis det er nødvendig å endre størrelse, lag en ny buffer og kopier dataene inn i den.
1// Slice an ArrayBuffer and copy to a new sized buffer.
2const original = new Uint8Array([1,2,3,4,5]).buffer;
3const part = original.slice(1, 4); // bytes 1..3
4console.log(new Uint8Array(part)); // Uint8Array [ 2, 3, 4 ]
5
6// Resize: create a new buffer and copy existing content
7const larger = new ArrayBuffer(10);
8const target = new Uint8Array(larger);
9target.set(new Uint8Array(original), 0);
10console.log(target); // first bytes filled with original data
- Siden
slice-metoden returnerer en nyArrayBuffer, kan du, hvis du prioriterer effektivitet eller deling av referanser, brukesubarray-metoden tilTypedArrayfor å referere til samme buffer.
Forskjellen mellom TypedArray.subarray og kopiering
TypedArray sitt subarray returnerer en ny visning som refererer til den samme ArrayBuffer.
1// subarray shares the same underlying buffer; modifying one affects the other.
2const arr = new Uint8Array([10,20,30,40]);
3const viewSub = arr.subarray(1,3); // shares memory
4viewSub[0] = 99;
5console.log(arr); // Uint8Array [10, 99, 30, 40]
- Delte visninger kan unngå kostnaden ved kopiering, men siden de refererer til samme buffer, må du være forsiktig med sideeffekter.
Kjeding av buffere (kombinere flere ArrayBuffer-objekter)
Siden ArrayBuffer har en fast lengde, må du lage en ny ArrayBuffer og kopiere dataene for å kombinere flere buffere.
1// Concatenate multiple ArrayBuffers
2function concatBuffers(buffers: ArrayBuffer[]): ArrayBuffer {
3 const total = buffers.reduce((sum, b) => sum + b.byteLength, 0);
4 const result = new Uint8Array(total);
5 let offset = 0;
6 for (const b of buffers) {
7 const u8 = new Uint8Array(b);
8 result.set(u8, offset);
9 offset += u8.length;
10 }
11 return result.buffer;
12}
13
14const a = new Uint8Array([1,2]).buffer;
15const b = new Uint8Array([3,4,5]).buffer;
16const c = concatBuffers([a, b]);
17console.log(new Uint8Array(c)); // [1,2,3,4,5]
- Hvis du ofte setter sammen store mengder data, er det mer effektivt å forhåndsberegne total størrelse og allokere en ny buffer kun én gang, slik som i denne koden.
Sende ArrayBuffer til en Worker (Transferable)
I nettleserens postMessage kan du overføre en ArrayBuffer som et "overførbart" objekt. Eierskapet kan overføres uten kopiering, noe som unngår kostnaden ved kopiering.
1// Example: posting an ArrayBuffer to a Worker as a transferable object (browser)
2const worker = new Worker('worker.js');
3const bufferToSend = new Uint8Array([1,2,3,4]).buffer;
4
5// Transfer ownership to the worker (main thread no longer owns it)
6worker.postMessage(bufferToSend, [bufferToSend]);
7
8// After transfer, bufferToSend.byteLength === 0 in many browsers (detached)
9console.log(bufferToSend.byteLength); // may be 0
- Ved å spesifisere objektene som skal overføres i et array som det andre argumentet til
postMessage, kan du overføre eierskap, uten kopiering, av overførbare objekter somArrayBuffer. - Etter overføringen blir bufferen "frakoblet" på den opprinnelige siden og kan ikke nås. Bruk av
SharedArrayBuffergir mulighet for samtidig tilgang fra flere tråder, men bruken innebærer sikkerhetskrav og miljøbegrensninger.
Håndtering i Node.js (konvertering med Buffer)
I Node.js kan du konvertere mellom Node.js sin binærtype Buffer og ArrayBuffer. Dette er nyttig når du vil støtte både nettlesere og Node.js med TypeScript.
1// Convert ArrayBuffer <-> Node.js Buffer
2// In Node.js environment:
3const ab = new Uint8Array([10,20,30]).buffer;
4const nodeBuffer = Buffer.from(ab); // ArrayBuffer -> Buffer
5console.log(nodeBuffer); // <Buffer 0a 14 1e>
6
7const backToAb = nodeBuffer.buffer.slice(
8 nodeBuffer.byteOffset,
9 nodeBuffer.byteOffset + nodeBuffer.byteLength
10);
11console.log(new Uint8Array(backToAb)); // Uint8Array [10,20,30]
Buffer.from(arrayBuffer)i Node.js lager vanligvis en kopi, men det finnes tilfeller hvor referansedeling er mulig, så vær oppmerksom på offset.
Ytelseshensyn og beste praksis
For å optimalisere ytelse og bruke ArrayBuffer effektivt, er det flere viktige punkter å være klar over. Nedenfor lister og forklarer vi praktiske beste praksiser.
-
Reduser antall kopier Når du håndterer store binærfiler, bruk
subarray(delt visning) eller overførbare objekter for å redusere antall kopier. -
Alloker store buffere på en gang Å gjentatte ganger allokere små buffere øker overhead. Hvis mulig, allokér en stor buffer på én gang og bruk deler av den ved behov.
-
Spesifiser endianness eksplisitt Når du håndterer flerbytes-verdier, bruk
DataViewog angi endianness eksplisitt. Big-endian er ofte standard for nettverksprotokoller.
Vanlige brukstilfeller
ArrayBuffer brukes mye både i nettlesere og i Node.js.
- Parsing og bygging av binære protokoller (behandling av header-informasjon med
DataView) - Mediebehandling som bilde- og lyddata (
fetch(...).then(res => res.arrayBuffer())) - Delt minne for WebAssembly (Wasm-minne opererer basert på
ArrayBuffer) - Avlasting av tung prosessering til Workers (overføre
ArrayBuffersom transferable)
Koden under er et eksempel på innhenting og analyse av binærdata.
1// Example: fetch binary data in browser and inspect first bytes
2async function fetchAndInspect(url: string) {
3 const resp = await fetch(url);
4 const ab = await resp.arrayBuffer();
5 const u8 = new Uint8Array(ab, 0, Math.min(16, ab.byteLength));
6 console.log('first bytes:', u8);
7}- Denne koden henter binærdata fra en hvilken som helst URL i nettleseren og viser de første byte. Koden laster inn data hentet via
fetch-API-et som enArrayBufferog inspiserer de første 16 byte med enUint8Array.
Sammendrag
ArrayBuffer er en representasjon av råminne, som gir effektive binæroperasjoner via TypedArray og DataView. Ved å unngå unødvendig kopiering og eksplisitt angi endianness, kan du oppnå sikker og høytytende binærprosessering.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.