javascript best way for error handling

روشی بهتر از try-catch برای مدیریت خطا در JS

مدیریت خطا و مشکل Try-Catch!

یکی از مهم ترین بخش های هر برنامه که گاهی بواسطه پیچیدگی کدها تبدیل به یک چالش بزرگ برای هر برنامه نویسی می شود. یکی از روش های مرسوم برای مدیریت خطا استفاه از بلوک های try-catch هست. در جاوااسکریپت نیز بطور مرسوم از همین روش استفاده می شود بالاخص در توابع غیرهمزمان. مشکلی که در استفاده از این روش وجود دارد، این است که در صورتی که شما درگیر یک مدیریت خطای چند لایه شوید، مجبور به استفاده از بلوک های try-catch تودر تو هستید که این باعث می شود کد شما به سرعت به سمت پیچیدگی پیش برود، خوانایی سخت و توسعه و نگهداری به مراتب سخت تر بشود.

async function fetchData() {
try {
const response = await fetch( "https://api.example.com/data" ) ;

try {
const data = await response.json( ) ;
return data;
}
catch (parseError) {
console. error( 'Failed to parse JSON: ',parseError);
} 
} catch (networkError) {
console.error( 'Network request failed: ' ,
networkError);
}
}

راه حل: عملگر =?

اما برای توسعه دهندگان جاوااسکریپت، راه حل، استفاده از عملگر =? است که به شما اطمینان می دهد که فضای مدیریت خطای شما ساده تر، تمیزتر و راحت تر باشد. این عملگر جدید جایگزینی ساده و موثر برای روش های قبلی است. در این روش به جای استفاده از بلوک های مجزای try-catch برای هر خطا، خطا در یک خط و بطور مستقیم دریافت می شود که این باعث سادگی و خوانایی کد شما خواهد شد.


چگونه کار می کند؟

خروجی این عملگر یک زوج مقدار به شکل مقابل است: [error, result]

در صورت بروز خطا مقدار آن در error قرار گرفته و در متغیر result مقدار null قرار می گیرد.

در صورت عدم دریافت خطا، خروجی در result قرار گرفته و error مقدار null خواهد داشت.

const [error, data] ?= await fetch("https://apt.example.com/data" ).json( )
if (error) {
console.error('Error occurred:', error);
} else {
console.log( 'Data fetched successfully:', data);
}

مزایای عملگر =?

  1. کد تمیزتر: با عملگر =? شما می توانید خطاهای احتمالی را در یک خط به دست بیاورید، آنهم بدون استفاده از بلوک های try-catch پیچیده و زیاد.
  2. مدیریت خطای متمرکز: به جای پخش کردن مدیریت خطا در بخش های مختلف تابع، همه چیز را در یک مکان متمرکز کنید تا برنامه شما خوانایی بیشتر و راحت تری داشته باشد.
  3. کارایی بهتر: بدون لایه های زیاد و تودرتوی try-catch، اجرای برنامه بهتر خواهد شد.
  4. مدیریت راحت تر asyc: برای توابع غیرهمزمان، این عملگر اجازه مدیریت خطا بدون فداکردن عملکرد را ارائه می دهد که بسیار مناسب API ها و وب اپلیکیشن ها می باشد.

قبل از عمل و بعد از عمل :)

روش قدیم (استفاده از try-catch)

async function loadConfig() {
try{
const fileContents = await
readFile( "config. json");
try{
const config = JSON. parse(fileContents);
return config;
} catch (parseError) {
console.error('Error parsing JSON:', parseError);
}
} catch (readError) {
console.error('Error reading file:', readError);
}
}

روش جدید (عملگر =?)

const [readError, fileContents] ?= await readFile("config. json");
const [parseError, config] = fileContents ? JSON.parse(fileContents)?= : [new Error("No file contents"),
null];
if (readError) {
console.error('Error reading file:', readError);
} else if (parseError) {
console.error('Error parsing JSON:', parseError);
} else {
console. log('Configuration loaded successfully:', config);
}
javascript tricks - iska

جذاب‌ترین ترفندهای جاوااسکریپت

جاوا اسکریپت یک زبان قدرتمند و انعطاف پذیر است و دانستن چند ترفند جالب می تواند کد شما را تمیزتر، سریعتر و کارآمدتر کند. در زیر 20 نکته و ترفند کاربردی جاوا اسکریپت وجود دارد که می توانید از آنها در برنامه های کاربردی دنیای واقعی برای بهبود روند توسعه خود استفاده کنید.

1. تغییر نام در یک مرحله هنگام تخریب شی

const user = { name: 'Alice', age: 25 };
const { name: userName, age: userAge } = user;
console.log(userName); // Alice
console.log(userAge);  // 25

2. بررسی وجود تابع قبل از فراخوانی با زنجیربندی اختیاری

const user = {
  getName: () => 'Alice',
};
console.log(user.getName?.());   // Alice
console.log(user.getAge?.());    // undefined

3. انتساب پیش فرض در صورت داشتن مقادیر null، undefined و یا مقادیر false مانند 0

let count;
count ||= 10;
console.log(count); // 10

4. تبدیل لیست گره ها به آرایه با عملگر گسترش (...)

const divs = document.querySelectorAll('div');
const divArray = [...divs];
console.log(Array.isArray(divArray)); // true

5. تخریب آرایه / شی با مقادیر پیش فرض برای جلوگیری از خطای undefined

const user = { name: 'Alice' };
const { name, age = 25 } = user;
console.log(age); // 25

6. حذف مقادیر نادرست(Falsy) از آرایه

const arr = [0, 'hello', null, 42, false, 'world'];
const filtered = arr.filter(Boolean);
console.log(filtered); // ["hello", 42, "world"]

7. 

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

Tailwind Safelist راهکاری برای مدیریت کلاس های پویا

Tailwind Safelist راهکاری برای مدیریت کلاس های پویا

Tailwind CSS یکی از فریمورک های مطرح است که به توسعه دهنده اجازه می دهد با استفاده از کلاس های از پیش تولید شده اقدام به ایجاد قالب های سفارشی کند. به همین دلیل است که Tailwind CSS از طیف وسیعی از کلاس ها پشتیبانی می کند که همین امر موجب ایجاد فایلی با حجم بالا می شود. برای حل این مشکل Tailwind CSS از یک ویژگی به نام PurgeCSS استفاده می کند که می تواند پس از ایجاد برنامه با پایش تمام فایل هایی که در فایل Config اعلام شده است، لیست کلاس های استفاده شده را شناسایی و کلاس های اضافی را از فایل نهایی حذف کند که این ویژگی منجر به ایجاد فایل نهایی به مراتب کوچک تر و سبک تر خواهد شد. با این وجود این ویژگی توانایی تشخیص کلاس هایی که بصورت شرطی و پویا ایجاد می شوند و یا کلاس هایی که از دیتابیس خوانده می شوند را ندارد. برای حل این مشکل Tailwind CSS از ویژگی دیگری به نام Safelist استفاده می کند که در این آموزش نحوه استفاده از آن را فرا می‌گیریم.

 

Tailwind Safelist چیست؟

Safelist یکی از ویژگی های Tailwind CSS است که برای تعریف کلاس هایی که توسط PurgeCSS تشخیص داده نمی شوند و از فایل نهایی حذف می شوند، استفاده می شود. معمولا کلاس هایی که بصورت پویا و بر اساس شرایط و یا از داخل بانک اطلاعاتی ایجاد می شوند، در پروسه PurgeCSS شناسایی نمی شوند. یکی از حالات معمول در این چالش، زمانی است که برنامه نویس رنگ هارا از سمت بک اند برای کاربر ارسال می کند یا زمانی که سیستم به مدیر اختیار تغییر رنگ در بخش های مختلف را می دهد. طبیعتا Tailwind توانایی تشخیص این کلاس ها را نداشته و در UI برنامه این کلاس ها نمایش داده نمی شوند. حال با اضافه کردن نام این کلاس ها به Safelist می توانید مطمئن باشید که چه این کلاس ها در پروسه PurgeCSS پیدا شوند چه نشوند از فایل نهایی شما حذف نخواهند شد.چگونه کلاس را در Tailwind Safelist اضافه کنیم؟برای افزودن کلاس به Safelist باید فایل tailwind.config.js را تغییر دهید. در این فایل آرایه ای از کلاس هایی که می خواهید از فایل نهایی حذف نشوند، بعنوان Safelist اضافه می کنید.

// tailwind.config.js
module.exports = {
  content: [
    // your content files here
  ],
  safelist: [
    'bg-red-500', 
    'text-white', 
    'hover:bg-red-700'
  ],  
  // other configurations
};

در این مثال کلاس های bg-red-500 و text-white و hover:bg-red-700 حتی در صورتی که در پروسه PurgeCSS پیدا نشوند، از فایل نهایی حذف نخواهند شد.

 

اما این آخر ماجرا نیست!

Tailwind CSS اما به همین بسنده نکرده است و برای افزایش کارایی و خوانایی برنامه، در قسمت Safelist پشتیبانی از Regex را نیز افزوده است. با این ویژگی اضافه کردن variants/modifiers و یا چندین رنگ، بسیار سریع و به سادگی قابل تعریف می باشد و از حجیم شدن لیست Safelist جلوگیری می کند. در زیر نمونه ای از استفاده Regex در Safelist را می بینید:

safelist: [
  {
    pattern: /from-(blue|green|indigo|pink|orange|rose)-200/
  },
  {
    pattern: /to-(blue|green|indigo|pink|orange|rose)-100/,
  },
],

با این روش بطور موثری ما 12 کلاس را به Safelist اضافه کردیم. این روش مدیریت لیست Safelist را به مراتب آسان تر و خواناتر می کند. همچنین همانگونه که در کد زیر می بینید امکان تعریف variant ها بدون تعریف Regex جدا قابل انجام است:

safelist: [
  {
    pattern: /text-(blue|green|indigo|pink|orange|rose)-(600|400)/,
    variants: ['hover'],
  },
  {
    pattern: /from-(blue|green|indigo|pink|orange|rose)-200/
  },
  {
    pattern: /to-(blue|green|indigo|pink|orange|rose)-100/,
  },
],

 

خلاصه چی گفتیم؟

Safelist ویژگی مفید Tailwind CSS است که برای اضافه نمودن کلاس هایی که در پروسه PurgeCSS تشخیص داده نمی شوند، استفاده می شود. با درک و استفاده از این ویژگی در سناریوهای مختلفی که ممکن است در طول برنامه رخ بدهد، توسعه دهنده یک پروژه قوی و قابل اطمینان خواهد داشت. با انجام چندین تمرین در سناریوهای مختلف، مطمئن شوید که فایل CSS نهایی شما کوچک و قابل اجرا خواهد بود.

راهکاری برای استفاده از فیلدهای یکتا در لاراول

راهکاری برای استفاده از فیلدهای یکتا در لاراول

مسأله:

قطعا همه ما با unique index type یا همون محدودیت فیلدهای یکتا کار کردیم و آشنا هستیم. هدف از تعریف این محدودیت روی ستون یا ستون‌های جدول در پایگاه داده جلوگیری از ورود داده‌های تکراری و اطمینان از عدم وقوع این مسئله در جدول مورد نظر هست.

امروز می‌خوایم در خصوص چالشی که استفاده از این محدودیت در لاراول برای ما به وجود میاره و راه حل اون با شما صحبت کنیم. حتما از  SoftDelete در لاراول استفاده کردین. خب مشکل دقیقا از همین‌جا شروع میشه. وقتی شما در یک مدل از SoftDelete استفاده می‌کنید قراره که حذف فقط به صورت منطقی اتفاق بیفته و نه فیزیکی. پس طبیعتا داده ای که منطقاً حذف شده، در جدول وجود داره و صرفا مقدار deleted_at از NULL به یک مقدار از نوع تاریخ و زمان تغییر کرده.

خب حالا وقتی ما داده‌ای رو به صورت Soft حذف می‌کنیم و در برنامه دیگه اثری از اون نمی‌بینیم، پس باید منطقا بتونیم دوباره تعریفش کنیم! اینجاست که پایگاه داده میاد وسط!!! و به ما میگه که اگر چه شما دیتا رو به صورت منطقی حذف کردی ولی از دید من حذفی انجام نشده! و حق نداری دیتای تکراری وارد کنی! پس باید چیکارکرد؟


راه حل:

راه حل ساده تر از اون چیزی هست که فکر می‌کنید.

✅فقط کافیه که حین تعریف یکتا بودن یک فیلد (مثلا email) اون فیلد رو به همراه deleted_at  یکتا کنید💡

این کار رو می توان در دیتابیس و یا در میگریشن انجام داد. به همین راحتی! حالا وقتی که یک رکود از جدول حذف منطقی میشه (یعنی deleted_at مقدار میگیره) اضافه کردن یک رکورد با مقادیر فیلدیکتایی که رکوردش قبلا حذف شده، ممکن میشه. برای اعتباریابی در سمت لاراول هم باید NULL بودن deleted_at رو چک کنید.