Kata Kunci using TypeScript dan Manajemen Sumber Daya Eksplisit

Kebocoran memori di lingkungan produksi sering kali berasal dari satu kesalahan: pengembang memperoleh sumber daya tetapi gagal melepaskannya.

Koneksi database tetap terbuka setelah terjadi kesalahan. File handle mengonsumsi sumber daya sistem. Klien WebSocket tetap terhubung ke server yang sudah mati. Hal ini terjadi ketika Anda mengandalkan pembersihan manual di dalam blok finally.

Kata kunci using di TypeScript menyelesaikan masalah ini. Ini adalah bagian dari proposal Manajemen Sumber Daya Eksplisit ECMAScript. Fitur ini menjamin pembersihan melalui pola disposable. Saat sebuah sumber daya keluar dari cakupannya (scope), TypeScript menjalankan metode pembuangannya (disposal method) secara otomatis.

Anda tidak lagi memerlukan blok finally manual. Anda tidak lagi lupa melakukan pembersihan. Anda tidak lagi mengalami kebocoran koneksi.

Cara kerjanya:

  • Kata kunci using memastikan pembuangan saat sumber daya keluar dari cakupan.
  • Sumber daya disposable mengimplementasikan Symbol.dispose untuk tugas sinkron atau Symbol.asyncDispose untuk tugas asinkron.
  • TypeScript mengubah deklarasi using menjadi blok try-finally dengan tumpukan pembuangan (disposal stack) otomatis.
  • Pola ini mencegah kebocoran yang disebabkan oleh pengembalian dini (early returns), pengecualian (exceptions) yang dilemparkan, atau kode yang terlupakan.

Gunakan using untuk sumber daya apa pun dengan masa pakai tertentu, seperti koneksi database, file handle, lock, atau timer.

Mekanisme ini menggunakan protokol pembuangan (disposal protocol). Objek mengimplementasikan metode yang menggunakan kunci Symbol.dispose. Saat cakupan berakhir melalui penyelesaian normal, pengembalian (return), atau pengecualian, TypeScript akan memanggil metode tersebut.

Contoh file handle:

class FileHandle {
  private handle: number;

  constructor(path: string) {
    this.handle = openFileSync(path);
  }

  [Symbol.dispose]() {
    if (this.handle !== -1) {
      closeFileSync(this.handle);
      this.handle = -1;
    }
  }

  read(buffer: Buffer): number {
    return readSync(this.handle, buffer);
  }
}

function processFile(path: string) {
  using file = new FileHandle(path);
  const buffer = Buffer.alloc(1024);
  file.read(buffer);
}

Pembuangan berjalan di dalam blok finally yang dihasilkan. Ini tetap berjalan meskipun fungsi melemparkan kesalahan atau melakukan pengembalian dini.

TypeScript mengelola tumpukan pembuangan (disposal stack). Ia membuang sumber daya dalam urutan terbalik dari cara Anda memperolehnya. Hal ini sesuai dengan urutan ketergantungan alami untuk sebagian besar logika pembersihan.

Untuk pembersihan asinkron, gunakan await using. Ini mengharuskan sumber daya untuk mengimplementasikan Symbol.asyncDispose. TypeScript akan menunggu (await) Promise yang dikembalikan sebelum melanjutkan.

Tiga aturan untuk keberhasilan:

  • Jangan melemparkan pengecualian di dalam metode pembuangan Anda. Sebaliknya, tangkap (catch) dan catat (log) kesalahan secara internal.
  • Jangan gunakan operasi asinkron di dalam metode Symbol.dispose yang sinkron. Gunakan Symbol.asyncDispose sebagai gantinya.
  • Ingatlah bahwa deklarasi using bersifat cakupan blok (block-scoped). Sumber daya di dalam blok if akan dibuang saat blok tersebut berakhir, bukan saat fungsi berakhir.

Pola ini memberikan keamanan dengan biaya runtime yang sangat kecil.

Sumber: https://dev.to/jsmanifest/typescript-using-keyword-and-explicit-resource-management-done-right-22pg