ArrayBuffer dalam TypeScript

ArrayBuffer dalam TypeScript

Artikel ini menerangkan mengenai ArrayBuffer dalam TypeScript.

Kami akan menerangkan ArrayBuffer dalam TypeScript secara langkah demi langkah, merangkumi asas hingga teknik praktikal.

YouTube Video

ArrayBuffer dalam TypeScript

ArrayBuffer ialah objek terbina dalam yang mewakili “ruang memori mentah” untuk data binari. Ia mewakili penimbal mentah dengan panjang tetap, di mana TypedArray atau DataView dilapiskan untuk tujuan membaca dan menulis.

Konsep Asas dan Ciri-ciri ArrayBuffer

ArrayBuffer ialah jujukan bait dengan panjang tetap. Anda menetapkan saiz dalam bait semasa menciptanya, dan panjangnya tidak boleh diubah selepas itu.

1// Create a new ArrayBuffer of 16 bytes.
2const buf = new ArrayBuffer(16);
3console.log(buf.byteLength); // 16
  • Kod ini mencipta penimbal kosong sebanyak 16 bait. Anda boleh menyemak saiz menggunakan byteLength.

TypedArray dan DataView — Pandangan untuk Mengendalikan Penimbal

ArrayBuffer tidak mempunyai keupayaan untuk membaca atau menulis data. Oleh itu, operasi sebenar dilakukan melalui TypedArray atau DataView, dengan menetapkan jenis seperti integer atau nombor titik apung serta endianness semasa mengakses 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 ]
  • Uint8Array ialah paparan susunan mengikut bait, dan boleh diakses seperti susunan biasa. Jika anda meletakkan beberapa paparan pada ArrayBuffer yang sama, mereka berkongsi memori yang sama untuk membaca dan menulis.

DataView: Membaca dan Menulis pada Sempadan dan Endian yang Separa

DataView berguna untuk membaca dan menulis secara terperinci mengikut bait, dan membolehkan anda memilih sama ada little atau big 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"
  • DataView membolehkan anda membaca dan menulis nilai dengan menentukan offset dalam memori, menjadikannya sesuai untuk melaksanakan protokol yang memerlukan pengendalian susunan bait rangkaian.

Penukaran antara Rentetan dan ArrayBuffer (TextEncoder / TextDecoder)

Untuk menukar teks kepada binari dan sebaliknya, gunakan TextEncoder dan 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.encode mengembalikan Uint8Array, jadi jika anda memerlukan ArrayBuffer, anda perlu merujuk kepada sifat .buffer miliknya. Dengan kaedah slice, anda boleh mengekstrak data yang diperlukan dengan menentukan offset dan panjang.

Penyingkiran dan Penyalinan ArrayBuffer

Kaedah slice mengembalikan ArrayBuffer baru. ArrayBuffer tidak boleh diubah saiz; jika perlu diubah saiz, buat penimbal baru dan salin data ke dalamnya.

 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
  • Oleh kerana kaedah slice mengembalikan ArrayBuffer baru, jika anda mementingkan kecekapan atau perkongsian rujukan, anda boleh menggunakan kaedah subarray pada TypedArray untuk merujuk kepada penimbal yang sama.

Perbezaan antara TypedArray.subarray dan Penyalinan

subarray daripada TypedArray mengembalikan paparan baru yang merujuk pada ArrayBuffer yang sama.

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]
  • Pandangan berkongsi boleh mengelakkan kos penyalinan, tetapi kerana ia merujuk kepada penimbal yang sama, anda perlu berhati-hati terhadap kesan sampingan.

Menggabungkan Penimbal (Menggabung Beberapa ArrayBuffer)

Oleh kerana ArrayBuffer mempunyai panjang tetap, untuk menggabungkan beberapa penimbal, cipta ArrayBuffer baru dan salin datanya.

 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]
  • Jika anda kerap menggabungkan sejumlah besar data, mengira terlebih dahulu saiz keseluruhan dan memperuntukkan penimbal baru hanya sekali, seperti dalam kod ini, adalah lebih cekap.

Menghantar ArrayBuffer ke Worker (Boleh Ditransfer)

Dalam postMessage pelayar, anda boleh memindahkan ArrayBuffer sebagai objek "transferable". Pemilikan boleh dipindahkan tanpa menyalin, yang mengelakkan kos menyalin.

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
  • Dengan menentukan objek untuk dipindahkan dalam satu array sebagai hujah kedua untuk postMessage, anda boleh memindahkan pemilikan tanpa menyalin, untuk objek transferable seperti ArrayBuffer.
  • Selepas dipindahkan, penimbal akan menjadi "detached" di pihak asal dan tidak boleh diakses. Penggunaan SharedArrayBuffer membolehkan akses serentak dari pelbagai urutan (thread), tetapi penggunaannya mempunyai syarat keselamatan dan sekatan persekitaran.

Pengendalian dalam Node.js (Pertukaran dengan Buffer)

Dalam Node.js, anda boleh menukar antara jenis binari Node.js Buffer dan ArrayBuffer. Ini berguna apabila menyasarkan kedua-dua pelayar dan Node.js dalam projek 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) dalam Node.js biasanya mencipta salinan, tetapi ada kes di mana perkongsian rujukan mungkin berlaku, jadi ambil perhatian pada offset.

Pertimbangan Prestasi dan Amalan Terbaik

Untuk mengoptimumkan prestasi dan mengendalikan ArrayBuffer dengan cekap, terdapat beberapa perkara penting yang perlu diambil kira. Di bawah, kami senaraikan dan terangkan amalan terbaik secara praktikal.

  • Kurangkan Bilangan Salinan Apabila mengendalikan binari besar, gunakan subarray (paparan perkongsian) atau transferable untuk mengurangkan salinan.

  • Peruntukkan Penimbal Besar Sekali Gus Peruntukan penampan kecil secara berulang meningkatkan beban kerja. Jika boleh, peruntukkan penampan besar sekali gus dan gunakan bahagiannya mengikut keperluan.

  • Nyatakan Endianness Secara Jelas Apabila mengendalikan nilai multibait, gunakan DataView dan nyatakan endian secara jelas. Big-endian selalunya menjadi standard untuk protokol rangkaian.

Contoh Kes Penggunaan Lazim

ArrayBuffer digunakan secara meluas dalam pelayar dan Node.js.

  1. Mengurai dan membina protokol binari (memproses maklumat header dengan DataView)
  2. Pemprosesan media seperti data imej dan audio (fetch(...).then(res => res.arrayBuffer())
  3. Memori dikongsi untuk WebAssembly (memori Wasm beroperasi berdasarkan ArrayBuffer)
  4. Memindahkan pemprosesan berat ke Workers (menghantar ArrayBuffer sebagai transferable)

Kod berikut ialah contoh bagaimana mendapatkan dan menganalisis data binari.

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}
  • Kod ini mengambil data binari dari mana-mana URL dalam pelayar dan memaparkan beberapa bait pertama. Kod ini memuatkan data yang diambil melalui API fetch sebagai ArrayBuffer dan menyemak 16 bait pertama menggunakan Uint8Array.

Ringkasan

ArrayBuffer ialah representasi memori mentah, membolehkan operasi binari yang efisien melalui TypedArray dan DataView. Dengan merekabentuk kod untuk mengelakkan penyalinan yang tidak perlu dan menyatakan endian dengan jelas, anda boleh mencapai pemprosesan binari yang selamat dan berprestasi tinggi.

Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.

YouTube Video