TypedArray in TypeScript

TypedArray in TypeScript

Dit artikel legt TypedArray in TypeScript uit.

We leggen TypedArray in TypeScript uit, inclusief praktische voorbeelden.

YouTube Video

TypedArray in TypeScript

TypedArray is een mechanisme voor het efficiënt verwerken van binaire data. Het is vooral handig voor lage-niveau binaire bewerkingen zoals grote afbeeldingsdata, netwerk-bytestromen en numerieke arrays voor WebGL.

Hoe maak je een ArrayBuffer aan

ArrayBuffer stelt een gebied met vaste lengte van bytes voor. Maak eerst een buffer aan en controleer de grootte en de byte-lengte.

1// Create an ArrayBuffer of 16 bytes
2const buffer: ArrayBuffer = new ArrayBuffer(16);
3console.log("buffer.byteLength:", buffer.byteLength); // 16
  • Deze code maakt een leeg gebied van 16 bytes aan. ArrayBuffer heeft zelf geen lees-/schrijffuncties, dus je benadert het via een TypedArray of DataView.

Soorten TypedArray

Er zijn veel soorten TypedArray, zoals de volgende:. Deze variëren afhankelijk van het gegevenstype en de grootte die ze verwerken.

TypedArray Gegevenstype Bitsgrootte
Int8Array 8-bits geheel getal 8 bits
Uint8Array Ongesigneerd 8-bits geheel getal 8 bits
Uint8ClampedArray Afgeknepen ongesigneerd 8-bits geheel getal 8 bits
Int16Array 16-bits geheel getal 16 bits
Uint16Array Ongesigneerd 16-bits geheel getal 16 bits
Int32Array 32-bits geheel getal 32 bits
Uint32Array Ongesigneerd 32-bits geheel getal 32 bits
Float32Array 32-bits drijvend-komma-getal 32 bits
Float64Array 64-bits drijvend-komma-getal 64 bits

Basis TypedArrays (Uint8Array, Int16Array, Float32Array, enz.)

TypedArray creëert een 'getypte weergave' bovenop een ArrayBuffer. Hieronder staan voorbeelden van het maken en gebruiken van enkele typische TypedArrays.

 1// Create a buffer and different typed views over it
 2const buf = new ArrayBuffer(8); // 8 bytes
 3
 4// Create views
 5const u8 = new Uint8Array(buf);    // 8 x uint8
 6const i16 = new Int16Array(buf);   // 4 x int16 (since each int16 is 2 bytes)
 7const f32 = new Float32Array(buf); // 2 x float32 (4 bytes each)
 8
 9console.log("Uint8 length:", u8.length);
10console.log("Int16 length:", i16.length);
11console.log("Float32 length:", f32.length);
  • Door meerdere weergaven op dezelfde ArrayBuffer te maken, kun je hetzelfde geheugen uitlezen en beschrijven in verschillende types of detailleringen. length van de view is het aantal elementen en byteLength is het aantal bytes.

Schrijven en lezen (byte-niveau operaties)

Wanneer je een waarde naar een TypedArray schrijft, worden de bijbehorende bytes in het geheugen aangepast. Je ziet deze wijzigingen wanneer je dezelfde buffer met een andere weergave uitleest.

 1// Demonstrate writing via one view and reading via another
 2const buffer2 = new ArrayBuffer(4);
 3const u8view = new Uint8Array(buffer2);
 4const u32view = new Uint32Array(buffer2);
 5
 6u8view[0] = 0x78;
 7u8view[1] = 0x56;
 8u8view[2] = 0x34;
 9u8view[3] = 0x12;
10
11console.log("Uint8 bytes:", Array.from(u8view)); // [120, 86, 52, 18]
12console.log("Uint32 value (platform endianness):", u32view[0]); // value depends on endianness
  • In dit voorbeeld schrijven we een bytevolgorde en lezen we hetzelfde gebied vervolgens uit als een 32-bit integer. Let op dat de uitvoer afhankelijk is van de endianness van de uitvoeringsomgeving.

Endianness (bytevolgorde) en DataView

DataView is handig als je endianness-problemen die afhankelijk zijn van de omgeving wilt beheersen. Met DataView kun je de endianness opgeven bij het lezen en schrijven.

 1// Use DataView to read/write with explicit endianness control
 2const b = new ArrayBuffer(4);
 3const dv = new DataView(b);
 4
 5// write little-endian 32-bit integer
 6dv.setUint32(0, 0x12345678, true);
 7
 8// read as little-endian and big-endian
 9const little = dv.getUint32(0, true);
10const big = dv.getUint32(0, false);
11
12console.log("little-endian read:", little.toString(16)); // "12345678"
13console.log("big-endian read:", big.toString(16));       // different value
  • DataView is een handig mechanisme om bytes gedetailleerd te lezen en te schrijven. Het ondersteunt verschillende types, zoals signed of unsigned integers en floating-point getallen, en je kunt de endianness (bytevolgorde) expliciet opgeven, wat erg handig is bij het implementeren van binaire protocollen.

Verschil tussen subarray en slice

De subarray van een TypedArray geeft een weergave terug die de originele buffer deelt, terwijl slice een nieuwe kopie oplevert. De prestaties en bijwerkingen verschillen afhankelijk van wat je gebruikt.

1const base = new Uint8Array([1, 2, 3, 4, 5]);
2
3const shared = base.subarray(1, 4); // shares underlying buffer
4const copied = base.slice(1, 4);    // copies data
5
6shared[0] = 99;
7console.log("base after shared modification:", base); // shows change
8console.log("copied remains:", copied);              // unaffected
  • Als je de gedeelde weergave wijzigt, verandert ook de originele array, wat onbedoelde neveneffecten kan veroorzaken. Als je de originele array veilig wilt behouden, kun je vooraf een kopie maken met slice().

Buffers kopiëren en type-omzetting (omzetting tussen TypedArrays)

We leggen uit hoe je data tussen TypedArrays kunt kopiëren en hoe je delen kunt plakken met de set-methode.

 1// Copy and convert between typed arrays
 2const src = new Float32Array([1.5, 2.5, 3.5]);
 3const dst = new Uint16Array(src.length);
 4
 5// Convert by mapping (explicit conversion)
 6for (let i = 0; i < src.length; i++) {
 7  dst[i] = Math.round(src[i]); // simple conversion rule
 8}
 9console.log("converted dst:", Array.from(dst)); // [2, 2, 4]
10
11// Using set to copy bytes (requires compatible underlying buffer or same element type)
12const src2 = new Uint8Array([10, 20, 30]);
13const dst2 = new Uint8Array(6);
14dst2.set(src2, 2); // copy src2 into dst2 starting at index 2
15console.log("dst2 after set:", Array.from(dst2)); // [0,0,10,20,30,0]
  • Als de elementtypes verschillen, moet je waarden omzetten, bijvoorbeeld afronden of bereik controleren, in plaats van ze alleen maar te kopiëren. set maakt snel kopiëren tussen TypedArrays van hetzelfde elementtype mogelijk.

Praktisch voorbeeld: Een parser van een binair protocol (eenvoudige implementatie)

Hier laten we een voorbeeld zien van een eenvoudige parser die binaire gegevens met een vast formaat leest, bestaande uit een 1-byte type, 2-byte gegevenslengte en een daaropvolgende payload.

 1// Simple binary message parser:
 2// format: [type: uint8][length: uint16 BE][payload: length bytes]
 3function parseMessages(buffer: ArrayBuffer) {
 4  const dv = new DataView(buffer);
 5  let offset = 0;
 6  const messages: { type: number; payload: Uint8Array }[] = [];
 7
 8  while (offset + 3 <= dv.byteLength) {
 9    const type = dv.getUint8(offset);
10    const length = dv.getUint16(offset + 1, false); // big-endian
11    offset += 3;
12    if (offset + length > dv.byteLength) break; // truncated
13    const payload = new Uint8Array(buffer, offset, length);
14    messages.push({ type, payload });
15    offset += length;
16  }
17
18  return messages;
19}
20
21// Example usage
22const buf = new ArrayBuffer(1 + 2 + 3 + 1 + 2 + 2); // two messages
23const dv = new DataView(buf);
24let off = 0;
25// first message: type=1, length=3, payload=[1,2,3]
26dv.setUint8(off, 1); dv.setUint16(off + 1, 3, false); off += 3;
27new Uint8Array(buf, off, 3).set([1, 2, 3]); off += 3;
28// second message: type=2, length=2, payload=[9,8]
29dv.setUint8(off, 2); dv.setUint16(off + 1, 2, false); off += 3;
30new Uint8Array(buf, off, 2).set([9, 8]);
31
32console.log(parseMessages(buf));
  • In dit voorbeeld wordt de header gelezen met DataView en wordt de payload-slice aangemaakt met Uint8Array. Endianness en controle op de buffergrootte zijn belangrijk.

Web API en TypedArray (Voorbeeld: binaire data ophalen)

Dit is een typisch voorbeeld van het verwerken van een ArrayBuffer die via een netwerkrequest is verkregen met behulp van een TypedArray.

 1// Example of fetching binary and mapping to typed array
 2async function fetchBinary(url: string) {
 3  const res = await fetch(url);
 4  const ab = await res.arrayBuffer();
 5  const view = new Uint8Array(ab);
 6  // process view...
 7  console.log("received bytes:", view.length);
 8  return view;
 9}
10
11// Usage (call in async context)
12// fetchBinary("/path/to/file.bin");
  • Je kunt de met Response.arrayBuffer() verkregen ArrayBuffer direct aan een TypedArray doorgeven. Het wordt gebruikt voor afbeeldingen, audio of aangepaste binaire protocollen.

Prestatietips en veelgemaakte valkuilen

Hier zijn enkele 'prestatietips' en 'veelvoorkomende valkuilen' die handig zijn bij het gebruiken van TypedArrays:.

  • Vermijd onnodig kopiëren Om grote data efficiënt te verwerken kun je onnodig kopiëren voorkomen door deelweergaven met subarray te maken of dezelfde ArrayBuffer door meerdere weergaven te delen.

  • Let op met endianness Bij netwerkcommunicatie of bestandsformaten wordt de volgorde van data (bytevolgorde) vaak gespecificeerd. Met DataView kun je de endianness expliciet bepalen bij lezen en schrijven, waardoor je onbedoelde verwarring voorkomt.

  • Let op de waardebereiken voor elk type Bijvoorbeeld, Uint8 kan alleen waarden van 0 tot 255 bevatten. Als je een negatieve waarde invoert, kan afkapping of doorslaan van waarden optreden, dus het is belangrijk om indien nodig conversieregels te definiëren.

  • Houd rekening met de belasting op garbage collection Het frequent opnieuw aanmaken van grote ArrayBuffers verhoogt de belasting van het geheugenbeheer. In prestatiekritische situaties kun je overwegen om de code zo te ontwerpen dat bestaande buffers zo veel mogelijk worden hergebruikt.

Samenvatting

TypedArray is een mechanisme om binaire data snel en efficiënt te verwerken. Door ArrayBuffer, dat een bytegebied met vaste lengte reserveert, te combineren met TypedArray of DataView waarmee je de inhoud met specifieke types leest of schrijft, kun je flexibele binaire operaties uitvoeren. Afhankelijk van je gebruikssituatie kun je kiezen tussen het gebruik van subarray/slice of DataView en je implementatie ontwerpen met aandacht voor endianness en kopieën.

Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.

YouTube Video