Skip to main content

Command Palette

Search for a command to run...

Membatalkan Fetch API dengan AbortController: Menjadikan Backend Hono Anda Lebih Efisien

Updated
4 min read
Membatalkan Fetch API dengan AbortController: Menjadikan Backend Hono Anda Lebih Efisien
A

I am an enthusiastic researcher and developer with a passion for using technology to innovate in business and education.

Dalam pengembangan web modern, interaksi asinkron menggunakan fetch API adalah hal yang lumrah. Namun, sering kali kita menghadapi skenario di mana sebuah request yang sedang berjalan perlu dibatalkan—misalnya, pengguna pindah ke halaman lain, mengetik kueri pencarian baru, atau secara manual mengklik tombol "Batal".

Di sinilah AbortController berperan di sisi klien. Tapi, apa dampaknya bagi backend? Jika klien membatalkan request, haruskah server tetap bekerja?

Artikel ini akan membahas cara menggunakan AbortController di sisi klien dan, yang lebih penting, bagaimana backend Hono Anda dapat mendeteksi pembatalan ini untuk menghentikan proses yang tidak perlu dan menghemat sumber daya server.


Bagian 1: Sisi Klien (Frontend) - Mengenal AbortController

AbortController adalah antarmuka (interface) bawaan di browser yang memungkinkan Anda membatalkan satu atau lebih proses web asinkron sesuai permintaan.

Cara kerjanya sederhana:

  1. Buat instance AbortController.

  2. Instance ini memiliki properti .signal (sebuah AbortSignal).

  3. Berikan signal ini ke fetch API sebagai opsi.

  4. Kapanpun Anda ingin membatalkan, panggil metode .abort() pada controller.

Ketika .abort() dipanggil, fetch akan segera dihentikan, dan promise yang dikembalikannya akan di-reject dengan DOMException yang bernama AbortError.

💡 Contoh Kode Sisi Klien (Vanilla JS)

Mari kita buat contoh sederhana dengan tombol "Mulai" dan "Batal".

HTML

<button id="startButton">Mulai Request (5 detik)</button>
<button id="cancelButton">Batalkan Request</button>
<pre id="log"></pre>

JavaScript

const startButton = document.getElementById('startButton');
const cancelButton = document.getElementById('cancelButton');
const log = document.getElementById('log');

let controller; // Kita simpan controller di scope yang lebih luas

startButton.onclick = async () => {
  // Buat AbortController baru SETIAP kali request dimulai
  controller = new AbortController();
  const signal = controller.signal;

  log.textContent = 'Memulai request ke server Hono...';

  try {
    const response = await fetch('/api/data-lambat', { signal });
    const data = await response.json();
    log.textContent = `Sukses: ${JSON.stringify(data)}`;
  } catch (err) {
    if (err.name === 'AbortError') {
      log.textContent = 'Request dibatalkan oleh klien!';
    } else {
      log.textContent = `Error: ${err.message}`;
    }
  }
};

cancelButton.onclick = () => {
  if (controller) {
    controller.abort(); // Kirim sinyal batal
    log.textContent = 'Mengirim sinyal pembatalan...';
  }
};

Pada titik ini, sisi klien sudah selesai. Ia tidak akan lagi menunggu respons dari server. Tapi, apakah server tahu?


Bagian 2: Sisi Server (Backend) - Mengapa Hono Peduli?

Ini adalah bagian yang krusial. Saat klien memanggil controller.abort(), browser akan menutup koneksi HTTP ke server.

Backend Hono Anda, yang berjalan di runtime modern (seperti Node.js, Deno, Bun, atau Cloudflare Workers), sangat cerdas. Ia dapat mendeteksi penutupan koneksi ini.

Runtime server akan meneruskan sinyal "abort" ini ke dalam objek Request yang diterima oleh Hono. Hono kemudian mengekspos sinyal ini melalui konteks (c).

Mengapa ini penting?

  • Hemat Sumber Daya: Jika request klien adalah kueri database yang berat atau panggilan ke API eksternal yang lambat, Anda tidak ingin server terus memprosesnya jika hasilnya tidak akan pernah dibaca.

  • Mencegah Pekerjaan Sia-sia: Dengan mendengarkan sinyal abort, server Hono Anda dapat segera menghentikan tugasnya, membebaskan CPU, memori, dan koneksi database.


Bagian 3: Implementasi Backend Hono yang 'Abort-Aware'

Hono memudahkan kita untuk mengakses sinyal pembatalan ini. Sinyal tersebut tersedia di c.req.signal.

Mari kita buat endpoint /api/data-lambat yang disimulasikan sebagai pekerjaan berat (misalnya, 5 detik) dan kita buat agar "sadar" akan pembatalan.

🔌 Contoh Kode Sisi Server (Hono)

JavaScript

// index.js (File server Hono Anda)
import { Hono } from 'hono';

const app = new Hono();

// Fungsi helper untuk simulasi delay yang bisa dibatalkan
const skippableDelay = (ms, signal) => {
  return new Promise((resolve, reject) => {
    // Jika sinyal sudah dibatalkan bahkan sebelum kita mulai, langsung reject.
    if (signal.aborted) {
      return reject(new Error('Client aborted'));
    }

    const timeout = setTimeout(resolve, ms);

    // Ini adalah intinya:
    // Dengarkan event 'abort' pada sinyal yang diberikan Hono
    signal.addEventListener('abort', () => {
      clearTimeout(timeout); // Batalkan timeout
      console.log('SERVER: Klien membatalkan, proses dihentikan!');
      reject(new Error('Client aborted')); // Reject promise
    });
  });
};

// Endpoint API kita
app.get('/api/data-lambat', async (c) => {
  const signal = c.req.signal; // Ambil sinyal dari konteks Hono

  try {
    console.log('SERVER: Proses berat dimulai...');

    // Tunggu 5 detik, tapi perhatikan sinyal 'abort'
    await skippableDelay(5000, signal);

    // Jika kode sampai di sini, artinya TIDAK dibatalkan
    console.log('SERVER: Proses berat selesai.');
    return c.json({ message: 'Pekerjaan selesai!' });

  } catch (err) {
    if (err.message === 'Client aborted') {
      // Kita bisa mengembalikan status khusus (non-standar) 
      // yang menandakan klien menutup request.
      return c.body(null, 499); // 499 Client Closed Request
    }

    // Handle error server lainnya
    return c.json({ error: 'Internal Server Error' }, 500);
  }
});

export default app;

Apa yang terjadi di sini?

  1. c.req.signal: Hono memberikan kita AbortSignal yang terhubung langsung ke koneksi HTTP klien.

  2. skippableDelay: Fungsi ini mensimulasikan pekerjaan. Ia menggunakan setTimeout untuk menunggu, tetapi juga menambahkan addEventListener('abort', ...) pada signal tersebut.

  3. Jika Klien Membatalkan:

    • Sisi klien memanggil controller.abort().

    • Browser menutup koneksi.

    • Runtime server mendeteksi ini dan memicu event 'abort' pada c.req.signal.

    • Listener kita di server aktif, clearTimeout dipanggil, dan promise di-reject.

  4. Hemat Sumber Daya: Blok try...catch di Hono menangkap error ini. Server berhenti memproses dan mengirim respons (yang mungkin tidak terkirim, tapi setidaknya prosesnya berhenti). Konsol server akan mencatat "SERVER: Klien membatalkan...".


Kesimpulan

Menggunakan AbortController bukan hanya sekadar "trik" frontend untuk mempercantik UI. Ini adalah pola desain full-stack yang penting untuk membangun aplikasi yang benar-benar responsif dan efisien.

Dengan memanfaatkan c.req.signal di Hono, Anda dapat membuat backend yang cerdas, yang tidak membuang-buang siklus CPU untuk request yang sudah ditinggalkan oleh pengguna. Ini adalah praktik terbaik yang membedakan aplikasi yang tangguh dan efisien dari yang lain.

More from this blog

F

Finlup ID | Sharing dunia teknologi dan coding

206 posts

Membedah Tren dan Teknologi yang Mengubah Dunia.