Bug kecil menyebabkan aplikasi Node.js mogok

 – Beragampengetahuan
14 mins read

Bug kecil menyebabkan aplikasi Node.js mogok – Beragampengetahuan

Bayangkan menerapkan layanan backend Node.js yang berfungsi sempurna dalam pengembangan, namun tiba-tiba mengalami gangguan produksi. Di laptop Anda semuanya berjalan dengan baik, tetapi di server langsung prosesnya terus-menerus ditutup secara tidak terduga.

Dalam kasus kami, pelakunya adalah penolakan janji yang tidak tertangani – orang hilang .catch() Setiap kali terjadi kesalahan, kode kami menyebabkan Node keluar secara tiba-tiba. Bug “kecil” inilah yang menyebabkan layanan stabil dan seringnya pemadaman. Dalam artikel ini, kita akan mempelajari bagaimana kesalahan konfigurasi penanganan kesalahan di Node/Express API dapat menyebabkan aplikasi mogok, dan cara mendiagnosis serta memperbaikinya untuk mencegah kerusakan di masa mendatang.

Contents

Cara mendapatkan penolakan yang tidak tertangani di aplikasi node

Ketika Promise ditolak dan tidak ada cara untuk menangani kesalahan tersebut, Node.js akan mengeluarkan a unhandledRejection peristiwa. Dalam versi Node modern (15+) ini Hentikan proses secara default Terjadi kesalahan fatal. Di versi yang lebih lama, prosesnya akan seperti itu Peringatan log dan terus berjalan, yang sering kali menyebabkan pengembang mengabaikan masalah tersebut, yang merupakan praktik berbahaya.

Dalam praktiknya, penolakan yang tidak tertangani mungkin tampak seperti Aplikasi tiba-tiba mogok Atau kegagalan “diam” yang aneh. Jika Anda menjalankan aplikasi Node melalui manajer proses atau kontainer, Anda mungkin memperhatikan bahwa aplikasi tersebut dimulai ulang secara tidak terduga atau mencatat kesalahan sebelum keluar. Misalnya, sebuah Node mungkin mencetak pesan seperti ini sebelum mati:

(node:12345) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 
This error originated either by throwing inside of an async function without a catch, 
or by rejecting a promise which was not handled with .catch(). 
(node:12345) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. 
In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.:contentReference[oaicite:2]{index=2}

Pada Node 16+ (di mana “masa depan” sekarang ada) prosesnya akan Penghentian setelah kesalahan seperti itu terjadi, biasanya disertai dengan tumpukan jejak pengecualian yang tidak tertangkap. Bagi klien atau pengguna akhir, setiap kali hal ini terjadi, layanan akan tampak offline atau tidak responsif (misalnya, permintaan API mulai gagal atau waktu habis).

Singkatnya, penolakan Promise yang tidak tertangani di Node seperti bom waktu: aplikasi dapat berjalan dengan baik hingga terjadi kesalahan pada fungsi async – lalu Browser atau klien melihat permintaan yang gagal (jika itu API) dan proses server Anda macet hampir tanpa penjelasan. Caranya adalah dengan mengidentifikasi situasi ini melalui petunjuk di log dan pesan kesalahan.

Mendiagnosis penolakan Janji yang tidak tertangani mengalami crash

Saat aplikasi Node.js Anda mogok “secara acak”, beberapa petunjuk dapat mengonfirmasi masalah penolakan yang tidak tertangani:

Periksa log server atau keluaran konsol

Carilah penyebutan “UnhandledPromiseRejectionWarning” atau tumpukan kesalahan yang berisi pengecualian yang tidak tertangkap. Jika Anda melihat Node mengeluh tentang penolakan yang tidak tertangani (atau DeprecationWarning tentang penolakan tersebut, seperti yang ditunjukkan di atas), itu pertanda kuat. Di Node 15+, Anda mungkin tidak mendapatkan peringatan – sebaliknya, proses akan keluar dengan kode bukan nol. Selain itu, periksa log restart manajer proses atau log sistem untuk melihat apakah proses Node dihentikan karena kesalahan yang tidak tertangkap.

Reproduksi menggunakan tanda debug

Jalankan aplikasi Anda di lingkungan pengembangan/pementasan dengan pelacakan penolakan janji yang ketat. Misalnya, mulai Node dengan perintah berikut --trace-warnings Tandai untuk mendapatkan jejak tumpukan penuh dari pembuatan Janji yang tidak tertangani. Anda juga dapat menggunakan node --unhandled-rejections=strict app.js Paksa Node mogok pada penolakan pertama yang tidak tertangani (bukan hanya dengan peringatan). Hal ini akan segera memunculkan masalah dan membantu Anda mengidentifikasi komitmen yang gagal.

Menggunakan penangan global (sementara)

Sebagai langkah diagnostik, Anda dapat melampirkan penangannya process.on('unhandledRejection') Batalkan pendaftaran alasan penolakan dan susun acaranya. Ini akan menangkap semua janji yang belum tertangani dan mencetak masalahnya (tanpa crash). Misalnya:

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

Dengan menggunakan metode di atas Anda seharusnya dapat mengidentifikasi Operasi atau janji mana dalam kode yang memunculkan kesalahan tanpa menangkapnya. Setelah Anda mengetahui hal ini, Anda dapat membidik jalur kode yang bermasalah.

Penanganan kesalahan untuk kesalahan konfigurasi: contoh kode (apa yang tidak boleh dilakukan)

Mari kita perhatikan contoh yang disederhanakan. Katakanlah kita memiliki server Express dengan titik akhir yang mengambil data dari database:

// server.js (Node/Express backend)
app.get('/api/data', async (req, res) => {
  const data = await getImportantData();  // Potentially throws or rejects
  res.json(data);  // No error handling around the await
});

Tampaknya sederhana – tapi itu adalah perangkap. jika getImportantData() Jika gagal (dengan asumsi kueri database memunculkan pengecualian atau mengembalikan janji yang ditolak), kesalahan akan muncul sebagai penolakan janji yang tidak tertangani karena tidak ada .catch() Atau coba/tangkap. Kesalahan yang tidak tertangkap dalam perutean asinkron di aplikasi Express 4.x Tidak akan tertangkap oleh middleware kesalahan default Express (Karena Express tidak mengetahui tentang janji yang ditolak kecuali kita menangkap dan meneruskannya).

Apa yang terjadi selanjutnya? Node memancarkan a unhandledRejection peristiwa tersebut, dan karena kami tidak menanganinya, Node menganggapnya sebagai kesalahan fatal yang tidak tertangkap. Server akan mencatat kesalahan (atau segera berhenti di Node 16+), yang mungkin menyebabkan proses terhenti. Dalam skenario dunia nyata, inilah yang terjadi: panggilan database yang berada jauh di dalam kode ditolak, dan karena fungsi tingkat yang lebih tinggi lupa menanganinya, seluruh proses Node terhenti.

Kesalahan umum lainnya adalah lupa await fungsi asinkron. Misalnya:

async function main() {
  getImportantData();  // forgot to await
  console.log("Done");
}
main();

Di Sini, getImportantData() Dipanggil tapi tidak ditunggu. Jika Anda menolak, tidak akan ada lagi .catch() Dan penolakan pada dasarnya “mengambang” di latar belakang. Hal ini juga menghasilkan penolakan yang tidak tertangani. Kekeliruan kecil, seperti hilang await Jadi ini bisa sama mengganggunya dengan tidak mengaktifkan penanganan kesalahan sama sekali.

Singkatnya, setiap kali kita memulai operasi asinkron tanpa penanganan kesalahan yang tepat, ada risiko error. Apakah ada orang yang hilang? catch Ada atau tidak ada dalam rantai komitmen try...catch Sehubungan dengan panggilan untuk menunggu, kesalahan konfigurasi ini membuat Node tidak memiliki instruksi tentang cara menangani kegagalan, sehingga strategi runtime-nya adalah Gagal parah (Mana yang lebih baik daripada menghancurkan negara secara diam-diam).

Perbaiki: Penanganan kesalahan yang tepat (contoh Express.js)

Setelah Anda mengidentifikasi Promise yang belum tertangani yang menyebabkan masalah, perbaikannya sederhana: Tangani kesalahan dari sumbernyaatau pastikan itu diteruskan ke pengendali yang tahu apa yang harus dilakukan. Dalam konteks Node/Express, Anda memiliki beberapa opsi:

Coba/tangkap dalam perutean asinkron

Perbaikan paling mudah untuk kode di atas adalah dengan membungkus menunggu dalam a try...catch. Dengan cara ini Anda mengetahui kesalahan dan dapat merespons atau meneruskannya dengan benar alih-alih membiarkannya menghentikan proses. Misalnya:

Di sini, jika getImportantData() melempar, blok tangkapan kami meneruskan kesalahan tersebut next(). Express kemudian akan mengirimkannya ke middleware penanganan kesalahan apa pun (seperti fungsi dengan tanda tangan) (err, req, res, next) Kirim 500 tanggapan). Kuncinya adalah Penolakan janji ditanganijadi Node tidak menganggapnya “tidak tertangani” atau mogok. Pola ini memastikan bahwa pengguna mendapatkan respons kesalahan alih-alih permintaan yang tertunda, dan proses kami tetap aktif.

Gunakan janji .catch() rantai komitmen murni

Jika Anda menggunakan janji tanpa async/awaitpastikan untuk menambahkan a .catch() di ujung rantai. Misalnya:

Hal ini menghasilkan hal yang sama – kesalahan apa pun ditangkap dan ditangani (mencatatnya dan merespons dengan status kesalahan), alih-alih melayang ke pengendali global Node.

const wrapAsync = fn => (req, res, next) => {
  fn(req, res, next).catch(next);
};
// Usage:
app.get('/api/data', wrapAsync(async (req, res) => {
  const data = await getImportantData();
  res.json(data);
}));

Memanfaatkan middleware/utilitas

Menambahkan try/catch secara manual di setiap rute bisa jadi membosankan dan rawan kesalahan. Di Express, Anda dapat menggunakan wrapper atau middleware untuk melakukan hal ini untuk Anda. Pendekatan yang umum adalah dengan membuat fungsi tingkat tinggi yang menggabungkan pengendali rute asinkron dan secara otomatis menangkap penolakan apa pun, meneruskannya ke next(). Misalnya:

suka perpustakaan kesalahan asinkron cepat Express juga dapat ditambal untuk menangani penolakan janji di penangan rute, sehingga menyelamatkan Anda dari kekacauan coba/tangkap di mana pun. Dalam skenario kami, kami menambahkan penanganan kesalahan yang diperlukan di sekitar kode yang bermasalah. Setelah kami melakukan ini, proses Node tidak lagi mengalami error – sebaliknya, proses Node mencatat kesalahan tersebut dan mengembalikan respons 500 ke klien, seperti yang diharapkan. Front end atau klien API mungkin melihat pesan kesalahan, namun seluruh layanan masih berjalan normal, yang jauh lebih baik daripada pemadaman total.

Catatan juga: Setelah memperbaiki masalah saat ini, pertimbangkan apakah kesalahan itu sendiri menunjukkan bug yang lebih dalam (misalnya fungsi yang seharusnya tidak dijalankan). Penanganan kesalahan dapat mencegah kerusakan, namun Anda tetap harus menyelidiki dan mengatasi akar penyebab kesalahan untuk meningkatkan ketahanan secara keseluruhan.

Akhirnya, jadi apa global process.on('unhandledRejection') penangan Apa yang kita gunakan dalam diagnosis? Anda dapat menyimpan versinya dalam produksi sebagai jaring pengaman jika Anda menggunakannya dengan bijak. Misalnya, Anda mungkin ingin mencatat penolakan tak terduga yang tidak tertangani dan mungkin melakukan pembersihan Matikan proses dengan baik. contoh:

process.on('unhandledRejection', (reason, promise) => {
  console.error("Unhandled Rejection at:", promise, "reason:", reason);
  // Recommended: clean up and exit, to avoid unknown state
  process.exit(1);
});

Ini memastikan jika Anda melakukan miss .catch Di tempat lain Anda akan mengetahuinya dari log dan prosesnya akan keluar (jika Anda memulai ulang, itu akan mengembalikannya). Namun, jangan mengandalkan ini sebagai penanganan kesalahan utama Anda ——Ini adalah upaya terakhir untuk mencegah kegagalan. Dokumentasi Node memperingatkan bahwa setelah pengecualian yang tidak tertangkap (atau penolakan yang tidak ditangani diperlakukan seperti itu), proses mungkin berada dalam keadaan tidak stabil dan harus dihentikan daripada dilanjutkan dengan baik. Jadi menggunakan penangan global untuk logging dan mematikan dengan baik, tapi Fokus untuk mengetahui di mana kesalahan terjadi.

Praktik terbaik untuk mencegah masalah penolakan yang tidak tertangani di Node.js

Beberapa tindakan pencegahan dapat mencegah Anda menghadapi skenario janji yang tidak tertangani:

  • selalu tepati janjimu: Setiap rantai janji harus diakhiri dengan .catch()dan setiap async/await Panggilan yang mungkin menimbulkan pengecualian harus dibungkus dengan coba/tangkap (atau ditangani). Secara umum, Jangan pernah gagal memenuhi janji Anda. Jika fungsi itu sendiri tidak perlu menangani kesalahan, pastikan fungsi tersebut mengembalikan janji kepada pemanggil yang akan menanganinya. Dengan cara ini, seseorang akan selalu menemukan kesalahannya.
  • Gunakan alat untuk menemukan kelalaian:Linter dan pemeriksa tipe dapat banyak membantu. Misalnya ESLint punya aturan seperti ini Tidak ada komitmen mengambang Tandai setiap janji yang tidak dinanti atau ditepati. Demikian pula, TypeScript dapat dikonfigurasi untuk memperingatkan tentang Janji yang tidak tertangani. Alat-alat ini ibarat jaring yang menangkap barang-barang yang “lupa menunggu” atau hilang .catch Lakukan tinjauan kode atau CI sebelum produksi berjalan.
  • Membungkus atau mengabstraksi penanganan kesalahan dalam kerangka kerja: Jika Anda menggunakan Express atau kerangka kerja serupa, terapkan pola atau pustaka yang menangani kesalahan asinkron secara global (mis. wrapAsync mode atau kesalahan asinkron ekspres, seperti yang ditunjukkan di atas). Hal ini mengurangi kemungkinan pengembang lupa menemukan bug di salah satu dari lusinan rute. Memiliki middleware penanganan kesalahan terpusat juga memastikan respons yang konsisten kepada klien ketika masalah muncul.
  • Gagal dengan cepat selama pengembangan: Jangan sembunyikan masalah ini selama pengembangan. Selalu jalankan server pengembangan dan staging Anda dengan versi atau pengaturan Node yang akan menyebabkan penolakan yang tidak tertangani. Seperti disebutkan sebelumnya, Node 15+ sudah mogok secara default. Jika Anda menggunakan versi LTS yang lebih lama, gunakan --unhandled-rejections=strict tandai untuk mensimulasikan perilaku ini. Tujuan kami adalah untuk mengetahui permasalahan sejak dini dan tidak membiarkannya berlarut-larut. Perlakukan peringatan apa pun tentang janji yang tidak tertangani sebagai kritis dan diperbaiki di tempat.
  • Menerapkan penangan global (hati-hati): Sebagai jaring pengaman, pertimbangkan untuk menambahkan process.on('unhandledRejection') Dan process.on('uncaughtException') Penangan dalam aplikasi produksi digunakan untuk mencatat kesalahan dan melakukan pembersihan di menit-menit terakhir. Ini dapat membantu Anda mengumpulkan informasi diagnostik jika terjadi masalah. Ingat saja: Jangan gunakan ini hanya untuk menekan kesalahan dan melanjutkan. Paling tidak, catat detailnya lalu keluar atau mulai ulang proses untuk menghindari berjalan dalam keadaan rusak. Praktik terbaiknya adalah tetap memperbaiki kode Anda daripada mengandalkan keseluruhan kode global.
  • Pantau dan uji skenario kesalahan: Gunakan alat pemantauan (APM, layanan pelacakan kesalahan seperti Sentry/New Relic) untuk menangkap penolakan yang tidak tertangani jika terjadi. Dan sertakan skenario kegagalan dalam pengujian Anda: misalnya, simulasikan penghentian database atau kegagalan panggilan API di lingkungan pengujian untuk memastikan kode Anda menangani penolakan dengan benar dan tidak error. Uji ketahanan ini dapat mengungkap tangkapan yang hilang sebelum mulai berproduksi.

Dengan mengikuti praktik ini, Anda akan membuat sistem “airbag” untuk aplikasi Node.js Anda yang menangkap kesalahan dengan baik daripada membiarkannya merusak seluruh layanan.

sebagai kesimpulan

Kesalahan kecil dalam penanganan Promise dapat berdampak besar – dalam kasus kami, satu Promise yang tidak tertangkap sudah cukup untuk melumpuhkan seluruh backend Node.js. Kabar baiknya adalah perbaikannya mudah: dengan menambahkan penanganan kesalahan yang tepat (beberapa baris kode), kami mengubah aplikasi yang rapuh dan rawan crash menjadi aplikasi yang kuat.

Penolakan janji yang tidak tertangani sering disebut sebagai “pembunuh diam-diam” aplikasi Node karena penolakan tersebut mungkin tidak selalu muncul di log pengembangan, namun dapat mendatangkan malapetaka dalam produksi. Kesimpulan utamanya adalah Jangan pernah membiarkan sebuah janji gagal. Kode dengan hati-hati (selalu sertakan .catch (atau coba/tangkap), alat dan kerangka kerja untuk menerapkan praktik yang baik, dan pengujian yang cermat, Anda dapat memastikan bahwa aplikasi Node.js Anda menangani kesalahan dengan baik alih-alih mogok saat terjadi kesalahan. Singkatnya: penuhi janji Anda dan aplikasi Node Anda akan menangani dirinya sendiri di bawah tekanan.

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Bug #kecil #menyebabkan #aplikasi #Node.js #mogok

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *