Error Handling di JavaScript: Try, Catch, Finally

Created at by Aris Munandar

Error handling adalah fondasi penting dalam pengembangan JavaScript. Tanpa teknik penanganan error yang baik, aplikasi bisa crash, UI bisa freeze, dan pengguna bisa mengalami pengalaman yang buruk. Artikel ini membahas secara mendalam cara menangani error di JavaScript, mulai dari dasar try catch finally hingga penanganan error pada Promise dan Async/Await.

Agar mudah dipahami pemula, artikel ini disusun per bagian, lengkap dengan contoh, ilustrasi, dan best practice yang dapat langsung diterapkan.

Baca juga: Asynchronous JavaScript: Callback, Promise, dan Async Await

Pengenalan Error Handling di JavaScript

Error handling di JavaScript adalah mekanisme untuk mendeteksi, menangkap, dan menangani error agar aplikasi tetap berjalan meskipun terjadi kesalahan. Dalam JavaScript, error bisa muncul karena berbagai hal: logika yang salah, nilai yang tidak sesuai, kesalahan sintaks, sampai masalah asynchronous seperti request API yang gagal.

Error handling memungkinkan developer:

  • Menghindari aplikasi crash total
  • Memberikan pesan error yang lebih ramah pengguna
  • Melacak sumber error dengan jelas (stack trace)
  • Memastikan proses tertentu tetap berjalan menggunakan finally

Dengan kata lain, error handling adalah “sabuk pengaman” dalam pemrograman JavaScript.

Kenapa Error Handling Penting

Tanpa error handling, sebuah error kecil bisa menghentikan seluruh jalannya aplikasi. Dalam aplikasi modern—terutama yang berjalan di browser—ini bisa sangat fatal.

Beberapa alasan utama kenapa error handling penting:

1. Menjaga pengalaman pengguna

Error yang tidak ditangani dapat membuat halaman kosong, tombol tidak bekerja, atau form gagal terkirim tanpa penjelasan. Dengan error handling, Anda bisa menampilkan pesan seperti:

“Oops, terjadi kesalahan. Coba lagi nanti.”

2. Mencegah aplikasi berhenti total

JavaScript menghentikan eksekusi suatu fungsi ketika error muncul. Jika tidak ditangani, error itu dapat menyebar ke bagian lain.

3. Membantu debugging

Dengan menangkap error, Anda bisa mencatat message, nama error, dan stack trace ke log atau server backend.

4. Penting untuk aplikasi asynchronous

Request API bisa gagal kapan saja. Promise bisa error. async/await bisa melempar exception. Tanpa error handling, Anda akan buta terhadap situasi tersebut.

Contoh Kasus Aplikasi Tanpa Error Handling

Bayangkan Anda memiliki fungsi sederhana yang mengambil data user dari API:

async function getUser() {
        const response = await fetch("https://api.example.com/user");
        const data = await response.json();
        console.log("User:", data.name);
}

getUser();Code language: JavaScript (javascript)

Apa yang terjadi jika:

  • Koneksi internet lambat?
  • Endpoint API sedang down?
  • API mengembalikan struktur data berbeda?
  • Server memberikan status 500?

Aplikasi langsung melempar error dan berhenti.

Di console Anda mungkin akan melihat:

Uncaught (in promise) TypeError: Failed to fetchCode language: JavaScript (javascript)

Dan proses console.log tidak akan berjalan. Jika ini terjadi pada aplikasi yang digunakan pelanggan, mereka akan merasa aplikasi “rusak”, padahal hanya kurang error handling.

Manfaat Error Handling untuk Pengembangan Web Modern

Error handling bukan lagi opsional dalam pengembangan web modern. Ada beberapa manfaat besar:

  1. Aplikasi lebih stabil
    Dengan try...catch dan finally, setiap error dapat ditangani secara terkendali.

  2. Mudah di-maintain
    Developer dapat dengan cepat mengetahui sumber masalah dari stack trace yang ditangkap.

  3. User lebih percaya pada aplikasi
    Tidak ada yang suka aplikasi yang tiba-tiba tidak bekerja. Pesan error yang sopan jauh lebih baik daripada crash.

  4. Lebih aman
    Error yang tidak ditangani kadang membuka celah bagi attacker untuk melihat informasi internal aplikasi.

  5. Wajib untuk fitur besar
    Seperti:

    • API fetching
    • Authentication
    • Sistem pembayaran
    • Pengolahan file
    • Aplikasi realtime

Jadi, error handling adalah pondasi penting agar aplikasi tetap profesional, aman, dan nyaman digunakan.

Jenis-Jenis Error dalam JavaScript

Memahami jenis-jenis error di JavaScript sangat penting sebelum mempelajari cara menangani error dengan try…catch atau Promise. Setiap jenis error memiliki ciri dan penyebab yang berbeda. Dengan mengenal semuanya, proses debugging akan jauh lebih cepat dan efisien.

Syntax Error

Syntax Error terjadi ketika JavaScript tidak bisa memahami kode karena kesalahan penulisan. Ini seperti salah ketik yang membuat interpreter tidak bisa membaca instruksi.

Contoh kesalahan umum:

function sayHello() {
    console.log("Hello"
}Code language: JavaScript (javascript)

Error yang muncul:

Uncaught SyntaxError: Unexpected token '}'Code language: JavaScript (javascript)

Ciri-ciri Syntax Error:

  • Terjadi sebelum kode dijalankan.
  • Biasanya disebabkan oleh kurung yang kurang, tanda kutip tidak lengkap, atau karakter ilegal.
  • Dapat diketahui secara cepat oleh editor modern melalui highlight merah.

Syntax Error tidak bisa ditangani dengan try…catch, karena script tidak akan jalan sama sekali sebelum kesalahan diperbaiki.

Runtime Error

Runtime Error muncul saat kode sudah berjalan, tetapi ada sesuatu yang tidak valid.

Contoh:

let user = null;
console.log(user.name);Code language: JavaScript (javascript)

Error:

Uncaught TypeError: Cannot read properties of null (reading 'name')Code language: JavaScript (javascript)

Ciri-ciri:

  • Terjadi ketika program sedang berjalan.
  • Bisa ditangani dengan try…catch.
  • Sering disebabkan oleh nilai yang tidak sesuai ekspektasi.

Runtime Error adalah jenis error yang paling sering dihadapi developer sehari-hari.

Logical Error

Logical Error adalah kesalahan logika dalam algoritma sehingga aplikasi menghasilkan output yang salah. Ini tidak menghasilkan pesan error otomatis, tapi hasilnya tidak sesuai.

Contoh:

function tambah(a, b) {
    return a - b; // seharusnya a + b
}

console.log(tambah(5, 2)); // Output: 3 (salah)Code language: JavaScript (javascript)

Ciri-ciri:

  • Tidak ada pesan error.
  • Sangat sulit dideteksi.
  • Biasanya ditemukan melalui testing atau pengecekan manual.

Logical Error adalah “musuh tersembunyi” karena tidak terlihat di console.

TypeError, ReferenceError, RangeError, EvalError, URIError

JavaScript memiliki banyak jenis error bawaan (built-in errors) yang muncul saat terjadi kondisi tertentu. Berikut penjelasan yang paling penting:

1. TypeError

Muncul ketika tipe data atau operasi tidak sesuai.

Contoh:

let fn = 123;
fn(); // memanggil angka sebagai fungsiCode language: JavaScript (javascript)

Error:

Uncaught TypeError: fn is not a functionCode language: JavaScript (javascript)

2. ReferenceError

Terjadi saat variabel dipanggil tetapi tidak dideklarasikan.

console.log(name); // variabel tidak adaCode language: JavaScript (javascript)

Error:

Uncaught ReferenceError: name is not definedCode language: JavaScript (javascript)

3. RangeError

Biasanya muncul saat nilai berada di luar batas yang diperbolehkan, misalnya length array negatif.

let arr = new Array(-5);Code language: JavaScript (javascript)

Error:

Uncaught RangeError: Invalid array lengthCode language: JavaScript (javascript)

4. EvalError

Berkaitan dengan fungsi eval() (jarang muncul kecuali dalam implementasi lama).

5. URIError

Error yang muncul ketika fungsi decode/encode URI berhadapan dengan karakter ilegal.

decodeURIComponent("%");Code language: JavaScript (javascript)

Error:

Uncaught URIError: URI malformedCode language: JavaScript (javascript)

Cara Membaca Pesan Error di Console

Salah satu keahlian dasar developer adalah membaca error di DevTools.

Format umum error:

TypeError: Cannot read properties of undefined (reading 'length')
    at getUserName (app.js:12)
    at main (app.js:22)Code language: JavaScript (javascript)

Penjelasannya:

  • TypeError → jenis error
  • Cannot read properties… → pesan error
  • at getUserName (app.js:12) → lokasi error (file + baris)
  • at main (app.js:22) → fungsi yang memanggilnya

Tips membaca error:

  • Fokus pada baris pertama (jenis + pesan).
  • Cek baris file yang ditunjuk.
  • Lihat stack trace untuk mengetahui alur error.
  • Jika error terkait Promise, sering muncul label: Uncaught (in promise)

Error Stack Trace dan Artinya

Stack trace adalah daftar urutan fungsi yang dieksekusi hingga terjadi error. Ini sangat membantu debugging karena memperlihatkan jalan lengkap eksekusi program.

Contoh stack trace:

TypeError: Cannot read properties of undefined (reading 'length')
    at getUserName (app.js:12)
    at main (app.js:22)Code language: JavaScript (javascript)

Cara membacanya:

  • Baris pertama menunjukkan pesan error.
  • Baris selanjutnya menunjukkan jejak fungsi dari bawah ke atas.
  • Fungsi paling bawah di daftar adalah pemicu awal error.

Manfaat stack trace:

  • Mengetahui asal-usul error.
  • Memudahkan debugging.
  • Sangat penting dalam error handling pada Promise dan async/await.

Dasar Try, Catch, Finally

Struktur try…catch…finally adalah fondasi utama dalam error handling JavaScript. Dengan memahami bagian-bagiannya, Anda dapat mencegah aplikasi crash, memberikan pesan error yang lebih jelas, dan menjaga proses penting tetap berjalan.

Cara Kerja Try

Bagian try adalah tempat Anda menulis kode yang berpotensi menghasilkan error. JavaScript akan menjalankan kode dalam blok try seperti biasa, tetapi jika terjadi kesalahan, eksekusi akan langsung dialihkan ke catch.

Contoh sederhana:

try {
    let data = JSON.parse("ini bukan JSON");
    console.log(data);
}Code language: JavaScript (javascript)

Apa yang terjadi?

  • JavaScript mencoba menjalankan kode.
  • Saat mencapai JSON.parse, terjadi error.
  • Eksekusi langsung dihentikan.
  • Baris setelah error tidak dijalankan.

Program melompat ke blok catch.

Tujuan try:

  • Mendeteksi potensi error.
  • Mengelompokkan blok kode kritis.
  • Mencegah aplikasi berhenti total.

Fungsi Catch

Blok catch digunakan untuk menangani error yang terjadi dalam try. Di dalamnya, Anda dapat:

  • Menampilkan pesan error
  • Menyimpan error ke log server
  • Menampilkan notifikasi ke user
  • Melakukan recovery (fallback)

Contoh:

try {
    let result = number.toUpperCase(); // number tidak didefinisikan
} catch (error) {
    console.error("Terjadi error:", error.message);
}Code language: JavaScript (javascript)

Output:

Terjadi error: number is not defined

catch menerima satu parameter, biasa diberi nama:

  • error
  • err
  • e

Objek error biasanya memiliki:

  • name → jenis error (TypeError, ReferenceError, dll)
  • message → deskripsi error
  • stack → jejak fungsi penyebab error

Yang membuat catch sangat penting:

  • Anda dapat menangani error tanpa menghentikan program.
  • Cocok untuk debugging dan logging.
  • Bisa digunakan untuk memberi fallback, misalnya:
let username;

try {
    username = getUserName();
} catch (e) {
    username = "Guest"; // fallback
}Code language: JavaScript (javascript)

Kapan Finally Dijalankan

finally adalah blok yang selalu dijalankan, terlepas dari apakah terjadi error atau tidak. Ini berguna untuk:

  • Membersihkan resource (misal: koneksi database)
  • Menghentikan loading spinner
  • Menutup modal
  • Mengembalikan state aplikasi

Contoh:

try {
    console.log("Memproses data...");
    throw new Error("Gagal memproses");
} catch (err) {
    console.log("Error:", err.message);
} finally {
    console.log("Selesai. Membersihkan...");
}Code language: JavaScript (javascript)

Output:

Memproses data...
Error: Gagal memproses
Selesai. Membersihkan...

finally tetap dijalankan meskipun:

  • Ada error
  • Tidak ada error
  • Ada return di dalam try
  • Ada return di dalam catch

Bahkan:

Perilaku Try/Catch pada Browser vs Node.js

Secara konsep, try/catch sama di keduanya, namun ada beberapa perbedaan kecil akibat lingkungan eksekusi.

  1. Browser

    • Error sering muncul akibat DOM, event handler, atau API browser.
    • Error pada asynchronous (Promise) tidak tertangkap otomatis oleh try/catch tanpa await.
    • Console browser menampilkan error dengan link file dan nomor baris.
  2. Node.js

    • Sering berkaitan dengan modul, file system, dan proses server.
    • Error fatal dapat menghentikan proses Node.
    • Menawarkan fitur tambahan seperti process.on(‘uncaughtException’).

Contoh di Node.js:

try {
    require("file-yang-tidak-ada");
} catch (e) {
    console.error("Error module:", e.message);
}Code language: JavaScript (javascript)

Contoh Kasus Simple

Contoh praktis error handling untuk pemula:

Kasus: Membaca input user yang tidak valid

function hitungDiskon(harga) {
    try {
        if (typeof harga !== "number") {
            throw new Error("Harga harus berupa angka");
        }

        let diskon = harga * 0.2;

        return diskon;

    } catch (error) {
        console.error("Error:", error.message);
        return 0; // fallback
    } finally {
        console.log("Fungsi hitungDiskon selesai dijalankan.");
    }
}

console.log(hitungDiskon(100000)); // 20000
console.log(hitungDiskon("seratus ribu")); // Error → 0Code language: JavaScript (javascript)

Penjelasan:

  • Error ditangkap di catch.
  • Program tetap berjalan normal.
  • finally tetap dijalankan, bahkan jika input tidak valid.

Throw: Membuat Error Sendiri

Selain menangani error, JavaScript memungkinkan kita membuat error secara manual menggunakan throw. Fitur ini penting untuk membuat validasi yang lebih kuat, menjaga kualitas data, dan mengontrol alur program dengan baik. Dengan throw, kita bisa menentukan kapan sebuah kondisi dianggap bermasalah dan harus dihentikan.

Kapan Menggunakan throw

Gunakan throw ketika Anda ingin:

1. Menghentikan eksekusi secara terkontrol

Jika ada kondisi yang tidak valid, Anda bisa segera menghentikan fungsi tanpa menunggu error alami muncul.

Contoh:

function bagi(a, b) {
    if (b === 0) {
        throw "Pembagian dengan nol tidak diperbolehkan!";
    }
    return a / b;
}

console.log(bagi(10, 2)); // 5
console.log(bagi(10, 0)); // ErrorCode language: JavaScript (javascript)

2. Memberikan pesan error yang lebih jelas

Error default JavaScript kadang tidak informatif. Dengan throw, Anda bisa membuat error yang mudah dipahami.

3. Melakukan validasi input

Validasi sangat umum dalam aplikasi web, seperti memeriksa email, nomor telepon, atau data form.

4. Mengontrol alur Promise dan async/await

Dalam async function, throw otomatis menghasilkan rejected Promise.

Contoh:

async function getUser() {
    throw new Error("Token tidak valid");
}Code language: JavaScript (javascript)

5. Menghasilkan error yang bisa di-catch

Anda dapat menangkap error yang dilempar menggunakan try…catch.

throw vs throw new Error

Banyak pemula bingung: harus pakai throw "pesan" atau throw new Error("pesan")?

Keduanya bisa, tapi sangat berbeda.

throw “pesan”

Anda melempar nilai string biasa, bukan objek Error.

Contoh:

throw "Terjadi kesalahan";Code language: JavaScript (javascript)

Kekurangannya:

  • Tidak memiliki name
  • Tidak memiliki stack trace
  • Sulit dideteksi dalam logging
  • Tidak standar

throw new Error(“pesan”)

Cara yang direkomendasikan.

throw new Error("Data user tidak ditemukan");Code language: JavaScript (javascript)

Keuntungannya:

  • Memiliki properti lengkap (name, message, stack)
  • Mudah dilacak di console
  • Bisa dibuat custom kelas error sendiri
  • Sesuai standar industri

Perbandingan singkat

TeknikDianjurkan?Alasan
throw "pesan"TidakTidak ada detail error, sulit dilacak
throw new Error("pesan")YaLebih rapi, lengkap, standar
throw new CustomError(...)Sangat direkomendasikanUntuk sistem error profesional

Membuat Custom Validation Error

Anda bisa membuat kelas error sendiri dengan mewarisi dari Error. Ini sangat bermanfaat ketika Anda ingin membedakan berbagai jenis error (validasi, otorisasi, database, dll).

Contoh membuat class custom:

class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }
}

function daftarUser(username) {
    if (username.length < 3) {
        throw new ValidationError("Username minimal 3 karakter!");
    }
    return "Pendaftaran berhasil";
}

try {
    daftarUser("ab");
} catch (error) {
    if (error instanceof ValidationError) {
        console.error("Validasi gagal:", error.message);
    } else {
        console.error("Error lain:", error.message);
    }
}Code language: JavaScript (javascript)

Keuntungan memakai custom error:

  • Memudahkan debugging
    Anda tahu persis jenis error yang muncul.

  • Bisa membuat kategori error
    Misalnya:

    • ValidationError
    • AuthenticationError
    • DatabaseError
    • NetworkError
  • Profesional dan siap production
    Aplikasi besar seperti React, Vue, Node.js semuanya memakai custom error.

Praktik Terbaik dalam Pembuatan Custom Error

Untuk menjaga kualitas codebase, berikut best practice yang dianjurkan:

1. Selalu gunakan kelas turunan dari Error

Bukan string atau object biasa.

class AppError extends Error {}Code language: JavaScript (javascript)

2. Tambahkan properti tambahan jika perlu

Misalnya statusCode untuk API.

class APIError extends Error {
    constructor(message, statusCode) {
        super(message);
        this.statusCode = statusCode;
        this.name = "APIError";
    }
}Code language: JavaScript (javascript)

3. Gunakan nama error yang konsisten

Nama format yang umum:

  • ValidationError
  • AuthError
  • NotFoundError

4. Jangan gunakan custom error untuk hal kecil

Misal:

❌ Tidak perlu membuat error khusus hanya untuk mengecek angka negatif.

Custom error perlu dipakai untuk kondisi besar dan penting.

5. Selalu sertakan pesan error yang jelas

Contoh buruk:

throw new Error("Error");Code language: JavaScript (javascript)

Contoh baik:

throw new Error("Username tidak boleh kosong");Code language: JavaScript (javascript)

6. Jangan lupa panggil super(message)

Jika tidak, properti message tidak akan terbentuk dengan benar.

7. Gunakan instanceof untuk identifikasi

Ini cara terbaik memisahkan jenis error.

if (error instanceof ValidationError) {
    // handle validasi
}Code language: JavaScript (javascript)

Error Handling pada Fungsi dan Modular Code

Dalam aplikasi JavaScript modern yang sudah modular dan terdiri dari banyak fungsi, tantangan utama adalah menempatkan error handling pada lokasi yang tepat. Kesalahan menaruh try…catch dapat menyebabkan kode berantakan, error tidak muncul, atau malah menimbulkan silent bug yang sulit dideteksi.

Bagian ini membahas bagaimana menangani error di level fungsi, modul, dan level global.

Menempatkan Error Handling di Level yang Tepat

Kesalahan terbesar pemula adalah:

  • Meletakkan try…catch terlalu banyak
  • Meletakkan try…catch terlalu dekat ke setiap baris kode
  • Meletakkan error handling di lokasi yang tidak strategis
  • Atau sebaliknya: tidak memasang error handling sama sekali

Prinsip utama:

  • Letakkan error handling sedekat mungkin dengan logika bisnis yang Anda ingin lindungi.

Contoh yang Salah (Terlalu banyak try/catch)

function prosesData(data) {
    try {
        let x = data.x;
    } catch (e) {}

    try {
        let y = data.y;
    } catch (e) {}

    try {
        return x + y;
    } catch (e) {}
}Code language: JavaScript (javascript)

Ini membuat debugging menjadi mimpi buruk, karena error “ditelan” di setiap tahap.

Contoh yang Benar (Satu try/catch untuk satu unit logika)

function prosesData(data) {
    try {
        const { x, y } = data;
        return x + y;
    } catch (error) {
        console.error("Gagal memproses data:", error.message);
        return null;
    }
}Code language: JavaScript (javascript)

Best practice penentuan lokasi try/catch:

  • Taruh di batas unit of work (fungsi, handler event, atau modul).
  • Jangan gunakan try…catch untuk validasi kecil—gunakan if.
  • Gunakan try…catch hanya untuk kode yang berpotensi melempar error.
  • Hindari menangkap error terlalu awal; biarkan naik jika perlu.

Menangkap Error di Dalam Fungsi

Fungsi adalah tempat paling strategis untuk menangkap error tertentu. Misal:

  • Validasi input
  • Panggilan API internal
  • Konversi data
  • Proses kalkulasi penting

Contoh:

function parseUser(jsonText) {
    try {
        const user = JSON.parse(jsonText);
        return user;
    } catch (error) {
        throw new Error("Format JSON tidak valid");
    }
}Code language: JavaScript (javascript)

Di sini fungsi parseUser memutuskan:

  • Error JSON asli tidak diteruskan apa adanya
  • Error dikonversi menjadi pesan yang lebih jelas
  • Error dilempar lagi ke level atas

Kapan menangkap error di dalam fungsi?

Gunakan teknik ini jika:

  • Fungsi perlu memberi error yang lebih spesifik
  • Anda ingin membungkus error eksternal menjadi error internal
  • Anda ingin memastikan fungsi tetap pure atau rapi
  • Fungsi dijalankan berkali-kali dan Anda ingin pesan konsisten

Meneruskan Error ke Atas (Error Propagation)

Terkadang, sebuah fungsi tidak boleh menangani error di dalamnya.

Biarkan error naik ke fungsi pemanggil (throw upward) agar dapat ditangani di level lebih tinggi.

Contoh:

function hitungTotal(items) {
    if (!Array.isArray(items)) {
        throw new Error("items harus berupa array");
    }

    return items.reduce((a, b) => a + b);
}

function main() {
    try {
        const total = hitungTotal("bukan array");
        console.log("Total:", total);
    } catch (error) {
        console.error("Terjadi kesalahan:", error.message);
    }
}

main();Code language: JavaScript (javascript)

Di sini:

  • hitungTotal() tidak menangkap error (SENGAJA)
  • Errornya diteruskan ke main()
  • main() yang menangani error secara global di proses itu

Kapan Anda harus melakukan error propagation?

  • Fungsi adalah bagian dari sistem yang lebih besar
  • Anda ingin error ditangani di suatu lapisan (misal “controller”, bukan “service”)
  • Modul kecil tidak perlu tahu cara menangani error
  • Menggunakan arsitektur seperti MVC, Clean Architecture, atau modul API

Error Handling Global (window.onerror / process.on)

Selain menangani error di level fungsi dan modul, JavaScript menyediakan error handler global untuk menangkap error yang tidak tertangkap (uncaught errors).

1. Global Error Handling di Browser

Browser menyediakan:

window.onerror

window.onerror = function (message, source, lineno, colno, error) {
        console.log("Global Error:", message);
        console.log("Lokasi:", source + ":" + lineno);
        console.log("Detail:", error);
};Code language: JavaScript (javascript)

Fungsi ini menangkap:

  • Error runtime yang tidak di-catch
  • Error syntax (kadang)
  • Error dari event handler

window.addEventListener("unhandledrejection")

Menangani Promise yang gagal tanpa .catch:

window.addEventListener("unhandledrejection", (event) => {
    console.error("Unhandled Promise:", event.reason);
});Code language: JavaScript (javascript)

2. Global Error Handling di Node.js

Node.js memberikan dua event khusus:

process.on("uncaughtException")

Menangkap error synchronous yang tidak tertangkap.

process.on("uncaughtException", (error) => {
    console.error("Uncaught Exception:", error);
    // idealnya lakukan restart server
});Code language: JavaScript (javascript)

process.on("unhandledRejection")

Untuk Promise tanpa .catch:

process.on("unhandledRejection", (reason) => {
    console.error("Unhandled Rejection:", reason);
});Code language: JavaScript (javascript)

Catatan Penting:

Menggunakan error handler global tidak menggantikan try/catch lokal, tetapi:

  • Menjadi laporan terakhir sebelum aplikasi mati
  • Berguna untuk logging server (Sentry, LogRocket, ELK)
  • Tidak disarankan untuk recovery logika bisnis
  • Lebih cocok untuk notifikasi dan debugging

Error Handling pada Asynchronous JavaScript

Asynchronous JavaScript menghadirkan tantangan tersendiri dalam error handling. Berbeda dengan kode sinkron yang mudah di-trace, error pada async code sering muncul terlambat, di luar blok eksekusi utama, atau tersembunyi dalam callback atau promise chain. Bagian ini membahas seluruh teknik modern untuk menangani error dalam kode asynchronous.

Tantangan Error Handling pada Async Code

Beberapa masalah umum dalam asynchronous JavaScript:

1. Error Tidak Terjadi di Tempat yang Sama dengan Kode Pemanggil

Contoh: callback dipanggil beberapa detik kemudian, sehingga try/catch awal tidak mempengaruhi error yang terjadi.

2. Callback Hell Memperburuk Trace Error

Semakin dalam callback bersarang, semakin sulit membaca alur kesalahan.

3. Promise Membutuhkan Catch Tersendiri

Error hanya tertangkap jika chain memiliki .catch().

4. Async/Await Butuh try/catch di Tiap Level

Jika tidak menggunakan try/catch, error dilempar sebagai rejected promise.

5. Silent Error

Misalnya, Promise yang tidak ditangkap akan menimbulkan “UnhandledPromiseRejection”.

Penanganan Error pada Callback

Callback menggunakan pola error-first:

function getData(callback) {
    setTimeout(() => {
        const error = Math.random() > 0.5 ? "Gagal ambil data" : null
        if (error) return callback(error)
        callback(null, { name: "John" })
    }, 1000)
}

getData((err, data) => {
    if (err) {
        console.error("Error:", err)
        return
    }
    console.log("Data:", data)
})Code language: JavaScript (javascript)

Ciri khas pola ini:

  • Parameter pertama = error
  • Callback harus selalu memeriksa error
  • Rawat error sedini mungkin untuk menghindari callback hell

Penanganan Error pada Promise (catch)

Error pada promise tertangkap menggunakan .catch().

Contoh:

const getUser = () => {
    return new Promise((resolve, reject) => {
        reject("User tidak ditemukan")
    })
}

getUser()
    .then(user => console.log(user))
    .catch(err => console.error("Error:", err))Code language: JavaScript (javascript)

Behavior penting:

  • Error dalam then otomatis masuk ke catch
Promise.resolve(10)
    .then(() => {
        throw "Oops"
    })
    .catch(err => console.log("Tertangkap:", err))Code language: JavaScript (javascript)

Promise.all dan Error yang Menghentikan Semua

Promise.all() akan langsung reject jika salah satu promise gagal.

Promise.all([
    Promise.resolve("A"),
    Promise.reject("Error pada B"),
    Promise.resolve("C")
])
.then(result => console.log(result))
.catch(err => console.error("Error:", err))Code language: JavaScript (javascript)

Output:

Error: Error pada BCode language: JavaScript (javascript)

Solusi: Gunakan Promise.allSettled() jika ingin menangkap semua hasil, termasuk error.

Promise.allSettled([
    Promise.resolve("A"),
    Promise.reject("Error B"),
    Promise.resolve("C")
]).then(console.log)Code language: JavaScript (javascript)

Output:

[
    { status: "fulfilled", value: "A" },
    { status: "rejected", reason: "Error B" },
    { status: "fulfilled", value: "C" }
]Code language: JavaScript (javascript)

Ini sangat berguna untuk tasks yang independen.

Error Handling pada Async/Await dengan try/catch

Async/await membuat penulisan lebih rapi, tetapi error harus ditangani dengan try/catch:

async function getData() {
    try {
        const result = await fetch("https://api.example.com/data")
        return await result.json()
    } catch (err) {
        console.error("Terjadi error:", err)
    }
}Code language: JavaScript (javascript)

Error di dalam async function → rejected promise

Jika function async tidak punya try/catch:

async function test() {
    throw "Oops"
}Code language: JavaScript (javascript)

test() menghasilkan rejected promise.

Contoh Kasus API Fetch (Async/Await)

Contoh lengkap:

async function getUser() {
    try {
        const response = await fetch("https://jsonplaceholder.typicode.com/users/1")

        if (!response.ok) {
            throw new Error("HTTP Error, status: " + response.status)
        }

        const data = await response.json()
        console.log("User:", data)

    } catch (err) {
        console.error("Gagal mengambil user:", err.message)
    }
}

getUser()Code language: JavaScript (javascript)

Error yang dapat terjadi:

  • Jaringan mati
  • Server down
  • Response tidak valid JSON
  • Status HTTP 4xx/5xx
  • Timeout (butuh AbortController)

Kesalahan Umum yang Perlu Dihindari

  1. Tidak memberi .catch() pada promise
    Dapat menyebabkan error global “UnhandledPromiseRejection”.

  2. Menggunakan try/catch pada kode async callback
    Try/catch tidak bekerja pada kode async yang tidak di-await.

  3. Tidak memvalidasi response HTTP
    fetch() tidak melempar error untuk status 404/500.

  4. Mengabaikan return dalam async
    Menghasilkan promise yang tidak pernah resolve.

  5. Menggabungkan callback + promise tanpa alasan
    Berpotensi membuat “callback-promise hell”.

  6. Tidak menempatkan error handling pada level yang tepat
    Harus ada error handling:

    • di tiap async function
    • di level global
    • di level UI (user feedback)

Debugging Error di JavaScript

Debugging adalah proses menemukan sumber masalah dalam kode. Dalam JavaScript, kemampuan debugging yang baik akan mempercepat penyelesaian error, meningkatkan kualitas aplikasi, dan mengurangi risiko bug berulang. Bagian ini membahas teknik dasar debugging modern, mulai dari membaca stack trace hingga mengoptimalkan penggunaan DevTools.

Membaca Stack Trace dengan Benar

Stack trace adalah daftar urutan fungsi yang dipanggil sebelum error terjadi. Ini sangat penting untuk menemukan lokasi sebenarnya dari error.

Contoh error:

Uncaught TypeError: Cannot read properties of undefined (reading 'name')
    at getUserName (script.js:15)
    at main (script.js:28)
    at script.js:32Code language: JavaScript (javascript)

Cara membacanya:

  1. Baris pertama: jenis error

    • TypeError: Cannot read properties of undefined
  2. Baris berikutnya: lokasi fungsi penyebab error

    • at getUserName (script.js:15)
      Ini adalah sumber error utama yang harus dicek dulu.
  3. Fungsi di atasnya: siapa yang memanggil fungsi error

    • at main (script.js:28)
  4. Baris terakhir: titik awal pemanggilan

    • script.js:32 adalah eksekusi awal yang memanggil main()

Console.log, Console.error, Console.warn

Console sangat membantu dalam debugging.

1. console.log()

Digunakan untuk melihat nilai variabel atau proses.

console.log("User:", user)Code language: JavaScript (javascript)

2. console.error()

Menampilkan error dengan styling merah → mudah terlihat.

console.error("Gagal load:", err)Code language: JavaScript (javascript)

3. console.warn()

Untuk menampilkan peringatan.

console.warn("Data tidak lengkap")Code language: JavaScript (javascript)

Tambahan penting:

  • console.table() → menampilkan array/object dalam bentuk tabel.
  • console.time() dan console.timeEnd() → memeriksa performa.
  • console.group() → mengelompokkan log agar rapi.

Menggunakan Debugger (Chrome DevTools)

DevTools memiliki fitur debugger yang menghentikan eksekusi kode secara otomatis.

Cara 1 — Menulis keyword debugger di kode:

function calculate() {
    debugger
    let x = 10
    let y = 20
    return x + y
}Code language: JavaScript (javascript)

Saat halaman dijalankan, DevTools akan berhenti di baris debugger.

Cara 2 — Membuka Sources Tab di Chrome:

  1. Buka DevTools → tab Sources
  2. Cari file JavaScript
  3. Klik nomor baris untuk membuat breakpoint
  4. Reload halaman
  5. Eksekusi akan berhenti tepat di baris tersebut

Keuntungan:

  • Melihat nilai variabel secara real-time
  • Mengontrol alur program
  • Melihat call stack dengan jelas
  • Bisa mengubah nilai variabel pada saat pause

Breakpoints, Step Over, Step Into

Breakpoints

Titik berhenti eksekusi kode. Digunakan untuk memeriksa keadaan aplikasi sebelum error.

Jenis breakpoints:

  • Line Breakpoint — berhenti pada baris tertentu
  • Conditional Breakpoint — berhenti hanya jika kondisi terpenuhi
    Contoh: klik kanan nomor baris → “Add conditional breakpoint”
    Kondisi: user.id === 5

Step Over (F10)

Menjalankan baris kode tanpa masuk ke fungsi yang dipanggil.

Cocok untuk:

  • Menghindari fungsi besar yang tidak relevan

Step Into (F11)

Masuk ke dalam fungsi yang dipanggil pada baris tersebut.

Cocok untuk:

  • Menelusuri error di fungsi internal

Step Out (Shift + F11)

Keluar dari fungsi saat ini dan kembali ke pemanggilnya.

Kapan digunakan:

  • Jika Anda masuk terlalu dalam dan ingin kembali ke alur utama

Tips Debugging untuk Pemula

1. Jangan langsung memperbaiki error—baca errornya dulu

Error JavaScript biasanya memberikan petunjuk lengkap:

  • Jenis error
  • Baris
  • File
  • Stack trace

2. Reproduksi error secara konsisten

Error yang bisa diulang → lebih mudah diperbaiki.

3. Gunakan console.log() secara strategis

Debugging bukan spam log:

  • Log input fungsi
  • Log output fungsi
  • Log nilai yang mencurigakan

4. Periksa apakah error disebabkan data kosong

80% error terjadi karena:

  • null
  • undefined
  • NaN
  • string kosong
  • array kosong

5. Isolasi bug

Pindahkan bagian kode ke area terpisah untuk mengetahui apakah error datang dari:

  • logika function
  • data
  • state UI

6. Gunakan “Pretty Print” untuk file minified

Jika error berasal dari file .min.js, klik tombol { } di DevTools.

7. Gunakan breakpoints daripada spam console.log

Breakpoints memberikan:

  • Nilai live variable
  • Arah alur eksekusi
  • Call stack penuh

8. Cek environment

Kadang error muncul karena:

  • Cache browser
  • Response API tidak sesuai
  • Perbedaan Node.js version

9. Coba jalankan di environment lain

Jika error hanya muncul di satu browser:

  • Cek compatibility
  • Cek polyfill

10. Periksa dokumentasi fungsi/library

Kadang error muncul karena salah format data atau aturan library.

Custom Error di JavaScript

Selain error bawaan JavaScript seperti TypeError, ReferenceError, dan RangeError, aplikasi modern sering membutuhkan custom error. Custom error memungkinkan developer:

  • Memberikan pesan error yang lebih spesifik
  • Menandai jenis error dengan jelas
  • Menangani error berbeda dengan cara berbeda di aplikasi besar

Kenapa Membuat Custom Error

Alasan membuat custom error:

  1. Klasifikasi error lebih jelas
    Misal membedakan error validasi dari error server.

  2. Memudahkan debugging
    Memudahkan tim untuk memahami error tanpa membaca message panjang.

  3. Mendukung arsitektur modular
    Setiap modul dapat melempar jenis error spesifik.

  4. Memberikan info tambahan
    Misal kode status HTTP, ID transaksi, atau level error.

Membuat Class Error Sendiri

Cara membuat custom error:

class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }
}Code language: JavaScript (javascript)

Penjelasan:

  • extends Error → mewarisi properti error standar
  • super(message) → memastikan message error tersimpan
  • this.name → menandai jenis error

Menyimpan Informasi Tambahan

Custom error bisa menyimpan data tambahan untuk membantu debugging atau reporting:

class APIError extends Error {
    constructor(message, statusCode, endpoint) {
        super(message);
        this.name = "APIError";
        this.statusCode = statusCode;
        this.endpoint = endpoint;
    }
}

const error = new APIError("Tidak dapat mengambil data", 500, "/users");
console.log(error.statusCode); // 500
console.log(error.endpoint);   // /usersCode language: JavaScript (javascript)

Menangani Custom Error di Aplikasi Besar

Di aplikasi besar, penting untuk menangkap dan memproses custom error secara berbeda.

Contoh:

try {
    throw new ValidationError("Nama wajib diisi");
} catch (err) {
    if (err instanceof ValidationError) {
        console.warn("Validasi gagal:", err.message);
    } else if (err instanceof APIError) {
        console.error("API Error:", err.message, err.statusCode);
    } else {
        console.error("Error lain:", err.message);
    }
}Code language: JavaScript (javascript)

Keuntungan:

  • Pesan error lebih spesifik untuk user dan developer
  • Bisa memisahkan error log antara validasi, server, atau runtime

Contoh Penggunaan Custom Error dalam Validasi Input

Praktik umum custom error: validasi input form.

class InputError extends Error {
    constructor(field, message) {
        super(message);
        this.name = "InputError";
        this.field = field;
    }
}

function validateUser(user) {
    if (!user.name) {
        throw new InputError("name", "Nama tidak boleh kosong");
    }
    if (!user.email.includes("@")) {
        throw new InputError("email", "Email tidak valid");
    }
    return true;
}

try {
    validateUser({ name: "", email: "arisexample.com" });
} catch (err) {
    if (err instanceof InputError) {
        console.error(`Error pada field ${err.field}: ${err.message}`);
    }
}Code language: JavaScript (javascript)

Output:

Error pada field name: Nama tidak boleh kosongCode language: JavaScript (javascript)

Manfaat:

  • Mudah mengaitkan error dengan field input
  • Memberikan pesan yang jelas ke UI
  • Memudahkan logging error di backend

Kesimpulan

Error handling di JavaScript adalah bagian penting untuk menulis kode yang aman, stabil, dan mudah dipelihara. Dengan memahami try…catch…finally, throw, serta custom error, developer dapat menangani berbagai jenis error, mulai dari syntax, runtime, hingga logical error, baik pada kode sinkron maupun asynchronous. Selain itu, penerapan error handling yang tepat memudahkan debugging, meminimalkan crash aplikasi, dan memberikan pengalaman pengguna yang lebih baik.

Setelah menguasai dasar-dasar ini, langkah selanjutnya adalah mengeksplorasi topik lanjutan seperti Promise, async/await, Fetch API, dan Observables. Memahami alur error pada asynchronous code dan teknik modern dalam menangani error akan membuat aplikasi web lebih robust, modular, dan siap untuk pengembangan skala besar.

1 JavaScript Dasar

2 JavaScript Menengah

Level Menengah fokus pada kemampuan yang lebih luas, seperti manipulasi DOM, event JavaScript, form validation, JSON, LocalStorage, SessionStorage, hingga asynchronous JavaScript dasar. Level ini membantu pengguna memahami bagaimana JavaScript bekerja untuk membuat website lebih interaktif dan dinamis, sangat relevan untuk tutorial dasar yang mengarahkan ke kemampuan membuat fitur web praktis.

3 JavaScript Lanjutan

4 JavaScript Mahir

5 JavaScript Ahli

Comments

Congrats, you have the opportunity to be the first commenter on this article. Have questions or suggestions? Please leave a comment to start discussion.

Leave comment

Alamat email Anda tidak akan dipublikasikan. Required fields are marked *

news-1701

sabung ayam online

yakinjp

yakinjp

rtp yakinjp

slot thailand

yakinjp

yakinjp

yakin jp

yakinjp id

maujp

maujp

maujp

maujp

slot mahjong

SGP Pools

slot mahjong

sabung ayam online

slot mahjong

SLOT THAILAND

article 888000081

article 888000082

article 888000083

article 888000084

article 888000085

article 888000086

article 888000087

article 888000088

article 888000089

article 888000090

article 888000091

article 888000092

article 888000093

article 888000094

article 888000095

article 888000096

article 888000097

article 888000098

article 888000099

article 888000100

cuaca 898100176

cuaca 898100177

cuaca 898100178

cuaca 898100179

cuaca 898100180

cuaca 898100181

cuaca 898100182

cuaca 898100183

cuaca 898100184

cuaca 898100185

cuaca 898100186

cuaca 898100187

cuaca 898100188

cuaca 898100189

cuaca 898100190

cuaca 898100191

cuaca 898100192

cuaca 898100193

cuaca 898100194

cuaca 898100195

article 710000191

article 710000192

article 710000193

article 710000194

article 710000195

article 710000196

article 710000197

article 710000198

article 710000199

article 710000200

article 710000201

article 710000202

article 710000203

article 710000204

article 710000205

article 710000206

article 710000207

article 710000208

article 710000209

article 710000210

article 710000211

article 710000212

article 710000213

article 710000214

article 710000215

article 710000216

article 710000217

article 710000218

article 710000219

article 710000220

article 710000221

article 710000222

article 710000223

article 710000224

article 710000225

article 710000226

article 710000227

article 710000228

article 710000229

article 710000230

article 710000231

article 710000232

article 710000233

article 710000234

article 710000235

article 710000236

article 710000237

article 710000238

article 710000239

article 710000240

article 710000241

article 710000242

article 710000243

article 710000244

article 710000245

article 710000246

article 710000247

article 710000248

article 710000249

article 710000250

artikel 338000001

artikel 338000002

artikel 338000003

artikel 338000004

artikel 338000005

artikel 338000006

artikel 338000007

artikel 338000008

artikel 338000009

artikel 338000010

artikel 338000011

artikel 338000012

artikel 338000013

artikel 338000014

artikel 338000015

artikel 338000016

artikel 338000017

artikel 338000018

artikel 338000019

artikel 338000020

artikel 338000021

artikel 338000022

artikel 338000023

artikel 338000024

artikel 338000025

artikel 338000026

artikel 338000027

artikel 338000028

artikel 338000029

artikel 338000030

artikel 338000031

artikel 338000032

artikel 338000033

artikel 338000034

artikel 338000035

artikel 338000036

artikel 338000037

artikel 338000038

artikel 338000039

artikel 338000040

artikel 338000041

artikel 338000042

artikel 338000043

artikel 338000044

artikel 338000045

artikel 338000046

artikel 338000047

artikel 338000048

artikel 338000049

artikel 338000050

artikel 338000051

artikel 338000052

artikel 338000053

artikel 338000054

artikel 338000055

artikel 338000056

artikel 338000057

artikel 338000058

artikel 338000059

artikel 338000060

artikel 338000061

artikel 338000062

artikel 338000063

artikel 338000064

artikel 338000065

artikel 338000066

artikel 338000067

artikel 338000068

artikel 338000069

artikel 338000070

artikel 338000071

artikel 338000072

artikel 338000073

artikel 338000074

artikel 338000075

artikel 338000076

artikel 338000077

artikel 338000078

artikel 338000079

artikel 338000080

artikel 338000081

artikel 338000082

artikel 338000083

artikel 338000084

artikel 338000085

artikel 338000086

artikel 338000087

artikel 338000088

artikel 338000089

artikel 338000090

article 238000411

article 238000412

article 238000413

article 238000414

article 238000415

article 238000416

article 238000417

article 238000418

article 238000419

article 238000420

article 238000421

article 238000422

article 238000423

article 238000424

article 238000425

article 238000426

article 238000427

article 238000428

article 238000429

article 238000430

article 238000431

article 238000432

article 238000433

article 238000434

article 238000435

article 238000436

article 238000437

article 238000438

article 238000439

article 238000440

news-1701
news-1701

sabung ayam online

yakinjp

yakinjp

rtp yakinjp

slot thailand

yakinjp

yakinjp

yakin jp

yakinjp id

maujp

maujp

maujp

maujp

slot mahjong

SGP Pools

slot mahjong

sabung ayam online

slot mahjong

SLOT THAILAND

article 888000081

article 888000082

article 888000083

article 888000084

article 888000085

article 888000086

article 888000087

article 888000088

article 888000089

article 888000090

article 888000091

article 888000092

article 888000093

article 888000094

article 888000095

article 888000096

article 888000097

article 888000098

article 888000099

article 888000100

cuaca 898100176

cuaca 898100177

cuaca 898100178

cuaca 898100179

cuaca 898100180

cuaca 898100181

cuaca 898100182

cuaca 898100183

cuaca 898100184

cuaca 898100185

cuaca 898100186

cuaca 898100187

cuaca 898100188

cuaca 898100189

cuaca 898100190

cuaca 898100191

cuaca 898100192

cuaca 898100193

cuaca 898100194

cuaca 898100195

article 710000191

article 710000192

article 710000193

article 710000194

article 710000195

article 710000196

article 710000197

article 710000198

article 710000199

article 710000200

article 710000201

article 710000202

article 710000203

article 710000204

article 710000205

article 710000206

article 710000207

article 710000208

article 710000209

article 710000210

article 710000211

article 710000212

article 710000213

article 710000214

article 710000215

article 710000216

article 710000217

article 710000218

article 710000219

article 710000220

article 710000221

article 710000222

article 710000223

article 710000224

article 710000225

article 710000226

article 710000227

article 710000228

article 710000229

article 710000230

article 710000231

article 710000232

article 710000233

article 710000234

article 710000235

article 710000236

article 710000237

article 710000238

article 710000239

article 710000240

article 710000241

article 710000242

article 710000243

article 710000244

article 710000245

article 710000246

article 710000247

article 710000248

article 710000249

article 710000250

artikel 338000001

artikel 338000002

artikel 338000003

artikel 338000004

artikel 338000005

artikel 338000006

artikel 338000007

artikel 338000008

artikel 338000009

artikel 338000010

artikel 338000011

artikel 338000012

artikel 338000013

artikel 338000014

artikel 338000015

artikel 338000016

artikel 338000017

artikel 338000018

artikel 338000019

artikel 338000020

artikel 338000021

artikel 338000022

artikel 338000023

artikel 338000024

artikel 338000025

artikel 338000026

artikel 338000027

artikel 338000028

artikel 338000029

artikel 338000030

artikel 338000031

artikel 338000032

artikel 338000033

artikel 338000034

artikel 338000035

artikel 338000036

artikel 338000037

artikel 338000038

artikel 338000039

artikel 338000040

artikel 338000041

artikel 338000042

artikel 338000043

artikel 338000044

artikel 338000045

artikel 338000046

artikel 338000047

artikel 338000048

artikel 338000049

artikel 338000050

artikel 338000051

artikel 338000052

artikel 338000053

artikel 338000054

artikel 338000055

artikel 338000056

artikel 338000057

artikel 338000058

artikel 338000059

artikel 338000060

artikel 338000061

artikel 338000062

artikel 338000063

artikel 338000064

artikel 338000065

artikel 338000066

artikel 338000067

artikel 338000068

artikel 338000069

artikel 338000070

artikel 338000071

artikel 338000072

artikel 338000073

artikel 338000074

artikel 338000075

artikel 338000076

artikel 338000077

artikel 338000078

artikel 338000079

artikel 338000080

artikel 338000081

artikel 338000082

artikel 338000083

artikel 338000084

artikel 338000085

artikel 338000086

artikel 338000087

artikel 338000088

artikel 338000089

artikel 338000090

article 238000411

article 238000412

article 238000413

article 238000414

article 238000415

article 238000416

article 238000417

article 238000418

article 238000419

article 238000420

article 238000421

article 238000422

article 238000423

article 238000424

article 238000425

article 238000426

article 238000427

article 238000428

article 238000429

article 238000430

article 238000431

article 238000432

article 238000433

article 238000434

article 238000435

article 238000436

article 238000437

article 238000438

article 238000439

article 238000440

news-1701
content-1701

sabung ayam online

yakinjp

yakinjp

rtp yakinjp

slot thailand

yakinjp

yakinjp

yakin jp

yakinjp id

maujp

maujp

maujp

maujp

slot mahjong

SGP Pools

slot mahjong

sabung ayam online

slot mahjong

SLOT THAILAND

article 888000081

article 888000082

article 888000083

article 888000084

article 888000085

article 888000086

article 888000087

article 888000088

article 888000089

article 888000090

article 888000091

article 888000092

article 888000093

article 888000094

article 888000095

article 888000096

article 888000097

article 888000098

article 888000099

article 888000100

cuaca 898100126

cuaca 898100127

cuaca 898100128

cuaca 898100129

cuaca 898100130

cuaca 898100131

cuaca 898100132

cuaca 898100133

cuaca 898100134

cuaca 898100135

cuaca 898100136

cuaca 898100137

cuaca 898100138

cuaca 898100139

cuaca 898100140

cuaca 898100141

cuaca 898100142

cuaca 898100143

cuaca 898100144

cuaca 898100145

cuaca 898100146

cuaca 898100147

cuaca 898100148

cuaca 898100149

cuaca 898100150

cuaca 898100151

cuaca 898100152

cuaca 898100153

cuaca 898100154

cuaca 898100155

cuaca 898100156

cuaca 898100157

cuaca 898100158

cuaca 898100159

cuaca 898100160

cuaca 898100161

cuaca 898100162

cuaca 898100163

cuaca 898100164

cuaca 898100165

cuaca 898100166

cuaca 898100167

cuaca 898100168

cuaca 898100169

cuaca 898100170

cuaca 898100171

cuaca 898100172

cuaca 898100173

cuaca 898100174

cuaca 898100175

article 710000151

article 710000152

article 710000153

article 710000154

article 710000155

article 710000156

article 710000157

article 710000158

article 710000159

article 710000160

article 710000161

article 710000162

article 710000163

article 710000164

article 710000165

article 710000166

article 710000167

article 710000168

article 710000169

article 710000170

article 710000171

article 710000172

article 710000173

article 710000174

article 710000175

article 710000176

article 710000177

article 710000178

article 710000179

article 710000180

article 710000181

article 710000182

article 710000183

article 710000184

article 710000185

article 710000186

article 710000187

article 710000188

article 710000189

article 710000190

article 710000191

article 710000192

article 710000193

article 710000194

article 710000195

article 710000196

article 710000197

article 710000198

article 710000199

article 710000200

psda 438000036

psda 438000037

psda 438000038

psda 438000039

psda 438000040

psda 438000041

psda 438000042

psda 438000043

psda 438000044

psda 438000045

psda 438000046

psda 438000047

psda 438000048

psda 438000049

psda 438000050

psda 438000051

psda 438000052

psda 438000053

psda 438000054

psda 438000055

psda 438000056

psda 438000057

psda 438000058

psda 438000059

psda 438000060

psda 438000061

psda 438000062

psda 438000063

psda 438000064

psda 438000065

psda 438000066

psda 438000067

psda 438000068

psda 438000069

psda 438000070

psda 438000071

psda 438000072

psda 438000073

psda 438000074

psda 438000075

psda 438000076

psda 438000077

psda 438000078

psda 438000079

psda 438000080

psda 438000081

psda 438000082

psda 438000083

psda 438000084

psda 438000085

psda 438000086

psda 438000087

psda 438000088

psda 438000089

psda 438000090

psda 438000091

psda 438000092

psda 438000093

psda 438000094

psda 438000095

psda 438000096

psda 438000097

psda 438000098

psda 438000099

psda 438000100

psda 438000101

psda 438000102

psda 438000103

psda 438000104

psda 438000105

psda 438000106

psda 438000107

psda 438000108

psda 438000109

content-1701