ArrayBuffer dalam TypeScript
Artikel ini menjelaskan tentang ArrayBuffer dalam TypeScript.
Kami akan menjelaskan ArrayBuffer dalam TypeScript secara bertahap, mulai dari dasar hingga teknik praktis.
YouTube Video
ArrayBuffer dalam TypeScript
ArrayBuffer adalah objek bawaan yang merepresentasikan “area memori mentah” untuk data biner. Ini merepresentasikan buffer mentah dengan panjang tetap, di mana TypedArray atau DataView digunakan untuk membaca dan menulis data.
Konsep Dasar dan Karakteristik ArrayBuffer
ArrayBuffer adalah urutan byte dengan panjang tetap. Anda menentukan ukuran dalam byte saat membuatnya, dan panjangnya tidak dapat diubah setelah itu.
1// Create a new ArrayBuffer of 16 bytes.
2const buf = new ArrayBuffer(16);
3console.log(buf.byteLength); // 16
- Kode ini membuat buffer kosong dengan ukuran 16 byte. Anda dapat memeriksa ukuran buffer menggunakan
byteLength.
TypedArray dan DataView — Tampilan untuk Memanipulasi Buffer
ArrayBuffer tidak memiliki kemampuan untuk membaca atau menulis data. Oleh karena itu, operasi sebenarnya dilakukan melalui TypedArray atau DataView, dengan menentukan tipe seperti bilangan bulat atau bilangan pecahan serta endianness saat 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 ]
Uint8Arrayadalah tampilan array byte dan dapat diakses seperti array biasa. Jika Anda menempatkan beberapa tampilan padaArrayBufferyang sama, mereka berbagi memori yang sama untuk membaca dan menulis.
DataView: Membaca dan Menulis pada Batas serta Endianness yang Fleksibel
DataView berguna untuk membaca dan menulis data per byte secara rinci, serta memungkinkan Anda menentukan 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"
DataViewmemungkinkan Anda untuk membaca dan menulis nilai dengan menentukan offset di memori, sehingga cocok untuk mengimplementasikan protokol yang memerlukan penanganan urutan byte jaringan.
Konversi antara String dan ArrayBuffer (TextEncoder / TextDecoder)
Untuk mengubah teks menjadi biner 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 harus mengacu pada properti.buffer. Dengan metodeslice, Anda dapat mengekstrak data yang diperlukan dengan menentukan offset dan panjangnya.
Memotong dan Menyalin ArrayBuffer
Metode slice mengembalikan ArrayBuffer yang baru. ArrayBuffer tidak dapat diubah ukurannya; jika perlu mengubah ukuran, buat buffer baru dan salin datanya 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
- Karena metode
slicemengembalikanArrayBufferbaru, jika Anda mengutamakan efisiensi atau berbagi referensi, Anda dapat menggunakan metodesubarraydariTypedArrayuntuk mengacu pada buffer yang sama.
Perbedaan antara TypedArray.subarray dan Penyalinan
subarray milik TypedArray mengembalikan tampilan 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]
- Tampilan bersama dapat menghindari biaya penyalinan, namun karena mereka mengacu pada buffer yang sama, Anda perlu berhati-hati terhadap efek samping.
Menggabungkan Buffer (Mengombinasikan beberapa ArrayBuffer)
Karena ArrayBuffer memiliki panjang tetap, untuk menggabungkan beberapa buffer buat 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 sering menggabungkan sejumlah besar data, menghitung ukuran total terlebih dahulu dan mengalokasikan buffer baru hanya sekali, seperti pada kode ini, akan lebih efisien.
Mengirimkan ArrayBuffer ke Worker (Transferable)
Dalam postMessage browser, Anda dapat mentransfer sebuah ArrayBuffer sebagai objek "transferable". Kepemilikan dapat dipindahkan tanpa penyalinan, sehingga menghindari biaya penyalinan.
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 yang akan ditransfer dalam sebuah array sebagai argumen kedua untuk
postMessage, Anda dapat memindahkan kepemilikan objek transferable sepertiArrayBuffertanpa menyalin. - Setelah transfer, buffer menjadi "detached" di sisi asal dan tidak dapat diakses. Penggunaan
SharedArrayBuffermemungkinkan akses simultan dari beberapa thread, tetapi penggunaannya memiliki persyaratan keamanan dan pembatasan lingkungan.
Penanganan di Node.js (Konversi dengan Buffer)
Di Node.js, Anda dapat mengonversi antara tipe biner Buffer dan ArrayBuffer. Ini berguna jika Anda menargetkan baik browser maupun Node.js dengan 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)di Node.js biasanya membuat salinan, tetapi ada kasus di mana referensi dapat dibagi, jadi perhatikan offset-nya.
Pertimbangan Performa dan Praktik Terbaik
Untuk mengoptimalkan performa dan menangani ArrayBuffer secara efisien, ada beberapa hal penting yang perlu diperhatikan. Di bawah ini, kami daftar dan jelaskan praktik terbaik secara praktis.
-
Kurangi Jumlah Penyalinan Saat menangani data biner besar, gunakan
subarray(tampilan bersama) atau transferable untuk mengurangi penyalinan. -
Alokasikan Buffer Besar Sekaligus Mengalokasikan buffer kecil secara berulang meningkatkan overhead. Jika memungkinkan, alokasikan buffer besar sekaligus dan gunakan bagiannya sesuai kebutuhan.
-
Tentukan Endianness Secara Eksplisit Saat menangani nilai multibyte, gunakan
DataViewdan secara eksplisit tentukan endianness-nya. Big-endian sering digunakan sebagai standar untuk protokol jaringan.
Contoh Kasus Penggunaan Umum
ArrayBuffer banyak digunakan baik di browser maupun Node.js.
- Parsing dan membangun protokol biner (memproses informasi header dengan
DataView) - Pemrosesan media seperti data gambar dan audio (
fetch(...).then(res => res.arrayBuffer())) - Memori bersama untuk WebAssembly (memori Wasm beroperasi berdasarkan
ArrayBuffer) - Mengalihkan pemrosesan berat ke Worker (mengirim
ArrayBuffersebagai transferable)
Kode berikut adalah contoh mendapatkan dan menganalisis data biner.
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}- Kode ini mengambil data biner dari URL mana pun di browser dan menampilkan beberapa byte pertama. Kode ini memuat data yang diambil melalui API
fetchsebagaiArrayBufferdan memeriksa 16 byte pertama menggunakanUint8Array.
Ringkasan
ArrayBuffer adalah representasi memori mentah, memungkinkan operasi biner yang efisien melalui TypedArray dan DataView. Dengan merancang agar menghindari penyalinan yang tidak perlu dan secara eksplisit menentukan endianness, Anda dapat mencapai pemrosesan biner yang aman dan berkinerja tinggi.
Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.