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 ]
Uint8Arrayialah paparan susunan mengikut bait, dan boleh diakses seperti susunan biasa. Jika anda meletakkan beberapa paparan padaArrayBufferyang 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"
DataViewmembolehkan 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.encodemengembalikanUint8Array, jadi jika anda memerlukanArrayBuffer, anda perlu merujuk kepada sifat.buffermiliknya. Dengan kaedahslice, 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
slicemengembalikanArrayBufferbaru, jika anda mementingkan kecekapan atau perkongsian rujukan, anda boleh menggunakan kaedahsubarraypadaTypedArrayuntuk 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 sepertiArrayBuffer. - Selepas dipindahkan, penimbal akan menjadi "detached" di pihak asal dan tidak boleh diakses. Penggunaan
SharedArrayBuffermembolehkan 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
DataViewdan 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.
- Mengurai dan membina protokol binari (memproses maklumat header dengan
DataView) - Pemprosesan media seperti data imej dan audio (
fetch(...).then(res => res.arrayBuffer()) - Memori dikongsi untuk WebAssembly (memori Wasm beroperasi berdasarkan
ArrayBuffer) - Memindahkan pemprosesan berat ke Workers (menghantar
ArrayBuffersebagai 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
fetchsebagaiArrayBufferdan menyemak 16 bait pertama menggunakanUint8Array.
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.