شما توی برنامه با ۳ دسته ارور روبرو میشید:
ارور هایی که throw میشن ارور هایی دسته ۱ و ۳ هستن. تو این موقع میتونیم از try catch یا then catch استفاده بکنیم و در نهایت یا ارور ها رو مستقیما هندل میکنیم یا که از یه میدلویر برای هندل کردن ارور ها استفاده میکنیم.
و ارور هایی که throw نمیشن ارور های دسته ۲ هستن. مثلا کاربر ایمیل مجاز وارد نکرده، تو این حالت دو گزینه روی میز هست: اولیش اینه که یه ارور throw کنی و مسیر بالا رو طی کنی، دومین گزینهی روی میز اینه که بیای ارور رو هندل بکنی. فرضا اجازهی ثبت نام بدی ولی به کاربر بگی که باید ایمیلتو درست بکنی.
آخرین مرحله نشون دادن ارور به کاربر هست. این مرحله ۳ روش پیاده سازی متفاوت داره:
وقتی یه ارور throw میشه جاوااسکریپت میاد اجرای برنامه رو متوقف میکنه و دنبال یه بلاک catch میگرده. فرض کن تو یه میدلویر اومدی تابع A رو call کردی و بعد تو تابع A تابع B رو call کردی. وقتی ارور تو تابع B رخ بده میاد با استفاده از call stack بر میگرده عقب تا به یه catch برسه.
اگر نرسه پروسه برنامه بسته میشه و ارور مشهور UnhandledPromiseRejection رو میبینید، در صورتی که promise بیس باشه و اگر هم callback باشه ارور رو تو کامند لاین میبینید.
وقتی میای همچین کاری میکنی چه انتظاری از جاوااسکریپت داری؟
try { fs.readFile('this-file-does-not-exist', function(error, data) { if (error) throw error; else console.log(data); }); } catch (error) { console.error(error); };
شاید تنها چیزی که انتظارش رو نداشته باشی این باشه که پروسه برنامه بسته بشه و بهت بگه همچین فایلی وجود نداره. چرا این کار رو میکنه؟ دلیلش خیلی ساده هست. وقتی شما این کد رو اجرا میکنی اول کدت کامپایل میشه و بعدش اجرا.
وقتی کدت داره اجرا میشه یه callback رو میاد تو callback queue قرار میده. هر وقت فایل سیستم نتیجه رو (چه ارور، چه محتوای فایل) برگردوند اون callback میاد اجرا میشه. ولی الان جاوااسکریپت try catch رو اجرا کرده و از روش رد شده. به همین خاطر دیگه try catch ای وجود نداره برای fs.readFile. پس ارور باعث بسته شدن برنامه میشه.
راه حل اینه که بیایم اون callback رو که error first هست به promise تبدیل بکنیم. برای این منظور میتونیم از کتابخونه ها یا از آبجکت Promise خود جاوااسکریپت استفاده بکنیم.
const { promisify } = require('util'); const fsReadFile = promisify(fs.readFile); async function A() { try { let data = await fs.readFile('this-file-does-not-exist'); console.log(data); } catch (error) { console.error(error); }; };
یا که بیای
function readFileAsync (filePath) { return new Promise(function (resolve, reject) { fs.readFile(filePath, function (error, data) { if (error) reject(error); else resolve(data); }); }); }; async function A() { try { let data = await fs.readFile('this-file-does-not-exist'); console.log(data); } catch (error) { console.error(error); }; };
حالا شما همین مثال ساده رو تعمیم بده به مورد استفاده خودت.
خب در مرحله بعد میرسیم به اینکه حالا این ارور ها رو هندل کردیم ولی اگه یه موقع ارور UnhandledPromiseRejection داد چکار بکنم. جوابش اینه:
process.on('unhandledRejection', error => { // Prints "unhandledRejection woops!" console.log('unhandledRejection', error.test); });
یا اگر داری وب اپ مینویسی میتونی همون دستورای بالا رو تو میدلویری که برای هندل کردن ارور های ۵۰۰ ساختی بزاری و بعدش وقتی اروری رخ داد که تو اصلا هندلش نکرده بودی صفحه ۵۰۰ رو به کاربر نشون بدی.
حالا که فهمیدی داستان تو این بخش ها چیه تازه اول راه هستی و قدم بعدیت این میتونه باشه که لاگ ها رو چکار بکنی. این مقاله رو بخون