Axios untuk Aplikasi Web Modern

Axios adalah klien HTTP berbasis Promise untuk browser dan Node.js yang memudahkan pemanggilan API dengan konfigurasi global, interceptors, pembatalan permintaan, penanganan galat yang konsisten, dan dukungan progress unggah/unduh. Artikel ini menjelaskan konsep inti, pola arsitektur, praktik aman, serta contoh siap salin untuk kebutuhan produksi.

Di proyek modern, kebutuhan HTTP jauh melampaui GET dan POST. Kita memerlukan retry cerdas, pelacakan progress, autentikasi yang aman, serta penyusunan lapisan layanan yang rapi. Axios dirancang untuk itu: mudah dikonfigurasi, dapat diperluas lewat interceptors, serta dapat dipakai di browser maupun Node.js. Pendeknya, ia menyatukan “kenyamanan” dan “ketertiban” dalam satu paket.

Opini: Gunakan Axios saat aplikasi bertumbuh dan Anda butuh kebijakan global, interceptors, dan pola layanan yang konsisten; gunakan fetch() murni bila kebutuhan sangat sederhana.

Apa Itu Axios & Kapan Dipakai

Axios adalah klien HTTP berbasis Promise untuk browser (XHR) dan Node.js. Kelebihannya mencakup konfigurasi global, interceptors permintaan/jawaban, transformasi data, pembatalan, dan batas waktu. Cocok untuk SPA, SSR, maupun layanan server.

Instalasi & Setup Cepat

Node.js/npm:

npm install axios
import axios from 'axios';
// atau CommonJS
// const axios = require('axios');

CDN (browser):

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
  // axios tersedia sebagai window.axios
  // axios.get('/api/health').then(console.log);
</script>

Membuat Instance & Kebijakan Global

Gunakan axios.create() agar konfigurasi tidak tersebar di mana-mana.

const api = axios.create({
  baseURL: 'https://api.contoh.com',
  timeout: 10000,
  headers: { 'Accept': 'application/json' }
});

// Opsional: serialisasi query terstruktur, cookie kredensial lintas-origin
// api.defaults.paramsSerializer = { indexes: null };
// api.defaults.withCredentials = true;

Contoh Dasar: GET, POST, PUT, PATCH, DELETE

// GET dengan parameter
const resp1 = await api.get('/produk', { params: { q: 'laptop', halaman: 1 } });
console.log(resp1.data);

// POST JSON
const resp2 = await api.post('/login', { email: 'user@contoh.com', password: '***' });

// PUT (replace) dan PATCH (partial update)
await api.put('/profil', { nama: 'Ayu', kota: 'Semarang' });
await api.patch('/profil', { kota: 'Bandung' });

// DELETE dengan payload (beberapa backend mendukung)
await api.delete('/keranjang', { data: { itemId: 123 } });

Interceptors: Auth, Logging, Transformasi

Interceptors memungkinkan kita menyisipkan logika sebelum/ sesudah request–response: menambahkan token, mengukur waktu, memetakan galat, dsb. Dokumentasi resmi menyediakan antarmuka use dan eject. :contentReference[oaicite:1]{index=1}

// Request interceptor: sisipkan token Bearer
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  config.metadata = { start: Date.now() };
  return config;
}, (error) => Promise.reject(error));

// Response interceptor: logging durasi & normalisasi galat
api.interceptors.response.use((response) => {
  const ms = Date.now() - (response.config.metadata?.start || Date.now());
  console.debug(`[API] ${response.config.method?.toUpperCase()} ${response.config.url} ${response.status} ${ms}ms`);
  return response;
}, (error) => {
  const res = error.response;
  return Promise.reject({
    message: res?.data?.message || error.message,
    status: res?.status || 0,
    data: res?.data,
    url: error.config?.url
  });
});

Penanganan Galat yang Konsisten

Secara bawaan, Axios menolak Promise untuk status di luar rentang sukses bawaan; perilaku ini dapat diubah lewat validateStatus. :contentReference[oaicite:2]{index=2}

// Anggap 404 bukan error fatal (resolve, bukan reject)
const r = await api.get('/produk/123', {
  validateStatus: (s) => (s >= 200 && s < 300) || s === 404
});
if (r.status === 404) {
  // tampilkan fallback
}

Pembatalan & Timeout

Axios mendukung pembatalan menggunakan AbortController (sesuai pola fetch) dan dapat dikombinasikan dengan timeout. :contentReference[oaicite:3]{index=3}

const controller = new AbortController();
const req = api.get('/pencarian', {
  params: { q: 'axios' },
  signal: controller.signal,
  timeout: 8000
});

// Batalkan bila pengguna mengganti kata kunci
// controller.abort();

try {
  const resp = await req;
  console.log(resp.data);
} catch (e) {
  if (e.name === 'CanceledError') console.warn('dibatalkan');
}

Otentikasi, Cookies, dan CSRF/XSRF

Untuk SSO berbasis cookie, aktifkan withCredentials dan pastikan server mengizinkan kredensial melalui CORS. Untuk framework yang menuntut token CSRF, sesuaikan nama cookie dan header XSRF. Dokumentasi konfigurasi Axios mencantumkan xsrfCookieName dan xsrfHeaderName. :contentReference[oaicite:4]{index=4}

// Kredensial lintas-origin (butuh dukungan CORS di server)
api.defaults.withCredentials = true;

// Contoh Django (ubah sesuai backend)
api.defaults.xsrfCookieName = 'csrftoken';
api.defaults.xsrfHeaderName = 'X-CSRFTOKEN';

Unggah/Unduh dengan Progress

Event onUploadProgress dan onDownloadProgress tersedia di browser. Pada lingkungan lain (misal React Native), dukungan berbeda. Rujuk konfigurasi resmi yang menandai fitur ini sebagai “browser only”. :contentReference[oaicite:5]{index=5}

// Unggah berkas dengan progress bar
const data = new FormData();
data.append('file', input.files[0]);

await api.post('/unggah', data, {
  onUploadProgress: (ev) => {
    const persen = Math.round((ev.loaded * 100) / (ev.total || 1));
    console.log('progress:', persen, '%');
  }
});

Permintaan Paralel & Paginasi

// Jalankan beberapa request paralel
const [p, k] = await Promise.all([
  api.get('/profil-saya'),
  api.get('/keranjang')
]);

// Paginasi sederhana
let halaman = 1, semua = [];
while (true) {
  const r = await api.get('/produk', { params: { halaman } });
  semua = semua.concat(r.data.item || []);
  if (!r.data.next) break;
  halaman++;
}

Retry & Exponential Backoff

Untuk kontrol penuh, implementasikan retry manual via interceptor respons.

function sleep(ms){ return new Promise(r => setTimeout(r, ms)); }

api.interceptors.response.use(undefined, async (error) => {
  const cfg = error.config || {};
  cfg.__retryCount = cfg.__retryCount || 0;

  // Retry hanya untuk galat jaringan atau status sementara
  const boleh = !error.response || [502, 503, 504].includes(error.response.status);

  if (boleh && cfg.__retryCount < 3) {
    cfg.__retryCount++;
    const delay = Math.min(1000 * 2 ** (cfg.__retryCount - 1), 8000);
    await sleep(delay);
    return api.request(cfg);
  }
  return Promise.reject(error);
});

Menyusun Service Layer

Pisahkan “transport” (Axios instance) dari “domain” (fungsi layanan) agar mudah diuji.

// transport.js
export const api = axios.create({ baseURL: 'https://api.contoh.com', timeout: 8000 });

// services/produk.js
import { api } from '../transport.js';
export async function cariProduk(q) {
  const r = await api.get('/produk', { params: { q } });
  return r.data; // mapping di sini agar komponen tetap bersih
}

TypeScript & Kontrak Tipe

// types.ts
export interface Produk { id: number; nama: string; harga: number; }

// layanan dengan tipe
import type { AxiosResponse } from 'axios';
import { api } from './transport';
import { Produk } from './types';

export async function detailProduk(id: number): Promise<Produk> {
  const r: AxiosResponse<Produk> = await api.get(`/produk/${id}`);
  return r.data;
}

Perbandingan Singkat dengan Fetch

AspekAxiosFetch
Penanganan galat bawaanMenolak Promise untuk status di luar rentang sukses (dapat diubah)Tidak menolak otomatis; perlu cek response.ok secara manual
Konfigurasi globalInstans, interceptors, header & baseURL mudahButuh pembungkus atau utilitas sendiri
Progress unggah/unduhTersedia event browser-onlyButuh trik ReadableStream untuk unduh; unggah bergantung implementasi
PembatalanAbortController didukungAbortController bawaan
Dukungan Node.jsAdapter Node siap pakaiPerlu ponyfill/library tambahan

Perbedaan penanganan galat dan pembatalan merujuk dokumentasi resmi Axios serta tinjauan komparatif terkini. :contentReference[oaicite:6]{index=6}

Keamanan & Praktik Baik

  • Jangan menaruh rahasia di klien. Token rahasia simpan di server; di klien hanya access token yang masa berlaku terbatas.
  • Aktifkan HTTPS. Hindari kebocoran header/kuesi.
  • CSRF/XSRF. Atur nama cookie dan header dengan benar; withCredentials butuh dukungan CORS di server. :contentReference[oaicite:7]{index=7}
  • Validasi status dengan sadar. Hindari menonaktifkan seluruh validasi tanpa alasan.
  • Batasi ulang-kirim. Gunakan retry hanya untuk galat yang aman diulang.

FAQ Ringkas

Apakah Axios otomatis mengurai JSON? Respons application/json disajikan sebagai objek JavaScript berdasarkan header dan adapter; Anda dapat menimpa perilaku via transformasi.

Mengapa onUploadProgress tidak berjalan di React Native? Karena event ini ditandai sebagai browser-only. Gunakan cara khusus RN. :contentReference[oaicite:8]{index=8}

Bagaimana memastikan seluruh respons (termasuk status galat) tetap resolve? Gunakan validateStatus: () => true lalu percabangkan berdasarkan status. :contentReference[oaicite:9]{index=9}

Kesimpulan

Axios menawarkan titik temu yang nyaman antara kemudahan dan ketertiban: konfigurasi global yang jelas, interceptors yang fleksibel, pembatalan yang modern, serta dukungan progress di browser. Dengan menyusun service layer, menata penanganan galat, serta menerapkan praktik aman (cookies, CSRF, CORS), Anda mendapatkan landasan HTTP yang mantap untuk aplikasi web maupun layanan Node.

Sumber/Referensi


Share the Post:

Related Posts