مدیریت خطا در برنامه‌های React

مدیریت خطا یک جنبه حیاتی در توسعه برنامه‌های کاربرپسند React است. به عنوان یک توسعه دهنده، همیشه نمی‌توانیم خطاها را پیش‌بینی کرده یا از آن‌ها جلوگیری کنیم، اما مطمئناً می‌توانیم نحوه رسیدگی به آن‌ها را کنترل نماییم.

در این مقاله قصد داریم تا استراتژی‌های کاربردی و مؤثر برای مدیریت خطا در برنامه‌های React را باهم بررسی کنیم. ما انواع مختلفی از خطاها، از خطاهای ساده در زمان اجرا گرفته تا خطاهای asynchronous را پوشش خواهیم داد. همینطور در مورد نحوه انتقال این خطاها به کاربران به روشی واضح بحث خواهیم کرد.

انواع مختلف خطاهای React

خطاهای سینتکس

خطاهای سینتکس زمانی رخ می‌دهند که در ساختار کد ما اشتباهی وجود داشته باشد. آن‌ها معمولاً به دلیل اشتباهات تایپی، کاراکترهای miss شده یا نادرست، یا استفاده اشتباه از المنت‌های زبان برنامه‌نویسی ایجاد می‌شوند. این خطاها مانع از تجزیه یا کامپایل صحیح کد می‌شود و در نتیجه برنامه اجرا نمی‌شود.

در ادامه برخی از سناریوهای متداول که منجر به خطاهای سینتکس می‌شوند را بررسی خواهیم کرد:

آکولاد، پرانتز و یا براکت‌های نادرست

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
function myFunction() {
if (true) {
console.log('Hello World';
}
}
// Correct
function myFunction() {
if (true) {
console.log('Hello World');
}
}
// Incorrect function myFunction() { if (true) { console.log('Hello World'; } } // Correct function myFunction() { if (true) { console.log('Hello World'); } }
// Incorrect
function myFunction() {
  if (true) {
    console.log('Hello World';
  }
}

// Correct
function myFunction() {
  if (true) {
    console.log('Hello World');
  }
}

در مثال بالا، یک خطای سینتکس رخ می‌دهد؛ زیرا یک پرانتز برای بسته شدن در دستور

console.log
console.logوجود ندارد.

فراموش کردن Semicolon

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const greeting = 'Hello World'
console.log(greeting)
// Correct
const greeting = 'Hello World';
console.log(greeting);
// Incorrect const greeting = 'Hello World' console.log(greeting) // Correct const greeting = 'Hello World'; console.log(greeting);
// Incorrect
const greeting = 'Hello World'
console.log(greeting)

// Correct
const greeting = 'Hello World';
console.log(greeting);

جاوااسکریپت از semicolon برای جداسازی عبارات استفاده می‌کند. بنابراین حذف آن‌ها می‌تواند منجر به خطاهای سینتکسی شود.

غلط املایی و کلمات کلیدی

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
funtion myFunction() {
console.log('Hello World');
}
// Correct
function myFunction() {
console.log('Hello World');
}
// Incorrect funtion myFunction() { console.log('Hello World'); } // Correct function myFunction() { console.log('Hello World'); }
// Incorrect
funtion myFunction() {
  console.log('Hello World');
}

// Correct
function myFunction() {
  console.log('Hello World');
}

در این مثال، یک خطای سینتکس رخ می‌دهد زیرا کلمه کلیدی

function
functionبه اشتباه
funtion
funtionنوشته شده است.

Unexpected Tokens

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const numbers = [1, 2, 3]
numbers.forEach(number => console.log(number))
// Correct
const numbers = [1, 2, 3];
numbers.forEach(number => console.log(number));
// Incorrect const numbers = [1, 2, 3] numbers.forEach(number => console.log(number)) // Correct const numbers = [1, 2, 3]; numbers.forEach(number => console.log(number));
// Incorrect
const numbers = [1, 2, 3]
numbers.forEach(number => console.log(number))

// Correct
const numbers = [1, 2, 3];
numbers.forEach(number => console.log(number));

این خطا ممکن است به دلیل miss شدن یک کاراکتر و یا وجود کاراکترهای اضافی رخ دهد که ساختار کد را به هم می‌ریزد.

برای مدیریت و رفع خطا سینتکس در برنامه‌های React باید کد خود را با دقت بررسی کرده و به پیام‌های خطای ارائه شده توسط محیط توسعه یا کنسول مرورگر توجه نماییم. این پیام‌ها اغلب خط و موقعیت خطا را نشان می‌دهند و به ما در شناسایی و تصحیح اشتباه کمک می‌کنند.

همچنین باید به این موضوع توجه داشته باشیم که حتی یک خطای سینتکس کوچک نیز می‌تواند تأثیر قابل توجهی بر روی عملکرد کد ما داشته باشد، بنابراین رسیدگی سریع به آن‌ها بسیار مهم است.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Corrected syntax
function MyComponent() {
return (
<div>
<p>Hello World</p>
</div>
);
}
// Corrected syntax function MyComponent() { return ( <div> <p>Hello World</p> </div> ); }
// Corrected syntax
function MyComponent() {
  return (
    <div>
      <p>Hello World</p>
    </div>
  );
}

خطاهای Reference

هنگامی که ما سعی می‌کنیم از متغیر یا تابعی استفاده کنیم که تعریف نشده است، خطاهای Reference در برنامه رخ می‌دهند. در این شرایط اساساً، مفسر یا کامپایلر نمی‌تواند مرجع متغیر یا تابع را در scope فعلی پیدا کند، در نتیجه منجر به خطای زمان اجرا می‌شود.

در ادامه چند سناریو متداول که منجر به خطاهای Reference می‌شوند را بررسی خواهیم کرد:

متغیرهای تعریف نشده

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
console.log(myVariable);
// Correct
const myVariable = 'Hello World';
console.log(myVariable);
// Incorrect console.log(myVariable); // Correct const myVariable = 'Hello World'; console.log(myVariable);
// Incorrect
console.log(myVariable);

// Correct
const myVariable = 'Hello World';
console.log(myVariable);

در این مثال، یک خطای Reference رخ می‌دهد زیرا

myVariable
myVariableقبل از اینکه تعریف شود مورد استفاده قرار گرفته است. تعریف متغیر قبل از استفاده از آن مشکل را حل می‌کند.

متغیرها یا توابع با غلط املایی

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const greeting = 'Hello World';
console.log(greting);
// Correct
const greeting = 'Hello World';
console.log(greeting);
// Incorrect const greeting = 'Hello World'; console.log(greting); // Correct const greeting = 'Hello World'; console.log(greeting);
// Incorrect
const greeting = 'Hello World';
console.log(greting);

// Correct
const greeting = 'Hello World';
console.log(greeting);

اگر اشتباه تایپی یا غلط املایی در نام متغیر یا تابع وجود داشته باشد، ممکن است یک خطای Reference رخ دهد. در این صورت با تصحیح املا آن، مشکل برطرف می‌شود.

مشکلات Scoping

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
function myFunction() {
if (true) {
const message = 'Hello World';
}
console.log(message);
}
// Correct
function myFunction() {
let message;
if (true) {
message = 'Hello World';
}
console.log(message);
}
// Incorrect function myFunction() { if (true) { const message = 'Hello World'; } console.log(message); } // Correct function myFunction() { let message; if (true) { message = 'Hello World'; } console.log(message); }
// Incorrect
function myFunction() {
  if (true) {
    const message = 'Hello World';
  }
  console.log(message);
}

// Correct
function myFunction() {
  let message;
  if (true) {
    message = 'Hello World';
  }
  console.log(message);
}

در این مثال یک خطای Reference رخ می‌دهد زیرا

message
messageدر scope بلاک
if
ifتعریف شده است و خارج از آن قابل دسترسی نیست. انتقال تعریف متغیر به scope وسیع‌تر، مشکل را برطرف می‌کند.

دسترسی به ویژگی‌های آبجکت‌های تعریف نشده

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const person = { name: 'John' };
console.log(person.age);
// Correct
const person = { name: 'John' };
console.log(person.age || 'Age not available');
// Incorrect const person = { name: 'John' }; console.log(person.age); // Correct const person = { name: 'John' }; console.log(person.age || 'Age not available');
// Incorrect
const person = { name: 'John' };
console.log(person.age);

// Correct
const person = { name: 'John' };
console.log(person.age || 'Age not available');

اگر سعی کنیم به یک ویژگی از یک آبجکت که

undefined
undefinedاست دسترسی پیدا کنیم، یک خطای Reference رخ می‌دهد. استفاده از بررسی‌های شرطی یا اطمینان از اینکه آبجکت به درستی مقداردهی اولیه شده است، می‌تواند از چنین خطاهایی جلوگیری کند.

برای مدیریت و رفع خطا Reference در برنامه‌های React، کد خود را به دقت بررسی می‌کنیم تا املای صحیح و تعریف متغیرها و توابع را به درستی داشته باشیم. باید اطمینان حاصل کنیم که متغیرها در scope مناسب تعریف شده‌اند و آبجکت‌ها قبل از دسترسی به ویژگی‌های آن‌ها، به درستی مقداردهی اولیه شده‌اند. درنهایت باید به پیام‌های خطا در کنسول توجه کنیم، زیرا اغلب اطلاعات ارزشمندی در مورد مکان و ماهیت خطای Reference ارائه می‌دهند.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Corrected reference
function MyComponent() {
const undefinedVariable = "I am defined now!";
return (
<div>
<p>{undefinedVariable}</p>
</div>
);
}
// Corrected reference function MyComponent() { const undefinedVariable = "I am defined now!"; return ( <div> <p>{undefinedVariable}</p> </div> ); }
// Corrected reference
function MyComponent() {
  const undefinedVariable = "I am defined now!";
  return (
    <div>
      <p>{undefinedVariable}</p>
    </div>
  );
}

خطاهای Type

خطاهای type در یک برنامه زمانی رخ می‌دهد که عملیاتی بر روی مقداری از تایپ داده، نادرست انجام می‌شود.

در جاوااسکریپت که یک زبان با تایپ پویا است، تایپ داده یک متغیر به صراحت تعریف نمی‌شود و در نتیجه می‌تواند در طول زمان اجرا تغییر کند.

خطاهای type معمولاً زمانی اتفاق می‌افتد که عملیاتی روی مقداری انجام می‌شود که آن عملیات خاص را پشتیبانی نمی‌کند.

در ادامه چند سناریو متداول که منجر به خطاهای Type می‌شوند را بررسی خواهیم کرد:

نوع داده نادرست برای یک عملیات

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const number = 42;
const result = number.toUpperCase();
// Correct
const number = 42;
const result = String(number).toUpperCase();
// Incorrect const number = 42; const result = number.toUpperCase(); // Correct const number = 42; const result = String(number).toUpperCase();
// Incorrect
const number = 42;
const result = number.toUpperCase();

// Correct
const number = 42;
const result = String(number).toUpperCase();

در این مثال، یک خطای type رخ می‌دهد زیرا

toUpperCase()
toUpperCase()یک متد رشته‌ای است و نمی‌توانیم آن را مستقیماً روی یک عدد اعمال نماییم. تبدیل عدد به رشته قبل از اعمال متد، مشکل را حل می‌کند.

انواع داده‌های نامتناسب در عملیات محاسباتی

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const result = 'Hello' * 5;
// Correct
const result = 'Hello'.repeat(5);
// Incorrect const result = 'Hello' * 5; // Correct const result = 'Hello'.repeat(5);
// Incorrect
const result = 'Hello' * 5;

// Correct
const result = 'Hello'.repeat(5);

تلاش برای انجام عملیات ضرب بر روی یک رشته و یک عدد، منجر به خطای type می‌شود. استفاده از متد رشته مناسب، مشکل را برطرف می‌کند.

مقادیر Undefined یا Null در عملیات

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const value = undefined;
const result = value.toLowerCase();
// Correct
const value = undefined;
const result = String(value).toLowerCase();
// Incorrect const value = undefined; const result = value.toLowerCase(); // Correct const value = undefined; const result = String(value).toLowerCase();
// Incorrect
const value = undefined;
const result = value.toLowerCase();

// Correct
const value = undefined;
const result = String(value).toLowerCase();

تلاش برای انجام عملیات بر روی یک مقدار

undefined
undefinedمی‌تواند منجر به یک خطای type شود. تبدیل مقدار value به رشته قبل از انجام عملیات خطا را برطرف می‌کند.

استفاده نادرست از توابع

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
const number = 42;
const result = String.toUpperCase(number);
// Correct
const number = 42;
const result = String(number).toUpperCase();
// Incorrect const number = 42; const result = String.toUpperCase(number); // Correct const number = 42; const result = String(number).toUpperCase();
// Incorrect
const number = 42;
const result = String.toUpperCase(number);

// Correct
const number = 42;
const result = String(number).toUpperCase();

استفاده نادرست از یک تابع، مانند تلاش برای فراخوانی

toUpperCase()
toUpperCase()در constructor
String
String، منجر به یک خطای type می‌شود. روش صحیح استفاده، شامل ایجاد یک نمونه رشته است.

برای مدیریت و رفع خطا type در برنامه‌های React، باید نوع داده‌ای متغیرهای خود و عملیاتی که می‌خواهیم انجام دهیم را به درستی بدانیم. ما می‌توانیم از توابع یا متدها برای تبدیل صریح مقادیر به نوع داده مورد نظر قبل از انجام عملیات استفاده نماییم. درنهایت، باید به پیام‌های خطا در کنسول توجه کنیم، زیرا اغلب ماهیت و محل خطای type را در کد ما نشان می‌دهند.

خطاهای Component Lifecycle

خطاهای Component Lifecycle در React زمانی رخ می‌دهد که مشکلات مربوط به متدهای Lifecycle یک کامپوننت React وجود داشته باشد.

کامپوننت‌های React در طول چرخه عمر خود مراحل مختلفی را طی می‌کنند و هر مرحله با متدهای خاصی همراه هستند. اگر از این متدها به درستی استفاده نکنیم و یا خطاهایی در آن‌ها وجود داشته باشد، می‌تواند منجر به رفتار غیرمنتظره و درنتیجه خطا در برنامه React ما شود.

component lifecycle  در React از سه مرحله اصلی تشکیل شده است:

Mounting:

  • constructor()
    constructor()
  • static getDerivedStateFromProps()
    static getDerivedStateFromProps()
  • render()
    render()
  • componentDidMount()
    componentDidMount()

Updating:

  • static getDerivedStateFromProps()
    static getDerivedStateFromProps()
  • shouldComponentUpdate()
    shouldComponentUpdate()
  • render()
    render()
  • getSnapshotBeforeUpdate()
    getSnapshotBeforeUpdate()
  • componentDidUpdate()
    componentDidUpdate()

Unmounting:

  • componentWillUnmount()
    componentWillUnmount()

در ادامه چند سناریو متداول که منجر به خطاهای Component Lifecycle می‌شوند را بررسی خواهیم کرد:

استفاده نادرست از setState

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
componentDidMount() {
this.setState({ data: fetchData() });
}
// Incorrect componentDidMount() { this.setState({ data: fetchData() }); }
// Incorrect
componentDidMount() {
  this.setState({ data: fetchData() });
}

استفاده از

setState
setStateبه طور مستقیم در داخل
componentDidMount
componentDidMountبدون در نظر گرفتن رفتار asynchronous می‌تواند منجر به ایجاد مشکلاتی شود. برای اطمینان از اینکه
setState
setState پس از fetch شدن داده‌ها فراخوانی می‌شود، توصیه می‌شود از یک تابع callback استفاده نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Correct
componentDidMount() {
fetchData().then(data => {
this.setState({ data });
});
}
// Correct componentDidMount() { fetchData().then(data => { this.setState({ data }); }); }
// Correct
componentDidMount() {
  fetchData().then(data => {
    this.setState({ data });
  });
}

عدم مدیریت صحیح عملیات‌های Asynchronous

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
componentDidUpdate() {
fetchData().then(data => {
this.setState({ data });
});
}
// Incorrect componentDidUpdate() { fetchData().then(data => { this.setState({ data }); }); }
// Incorrect
componentDidUpdate() {
  fetchData().then(data => {
    this.setState({ data });
  });
}

انجام عملیات‌های asynchronous به طور مستقیم در داخل

componentDidUpdate
componentDidUpdateمی‌تواند منجر به ایجاد به حلقه‌های بی‌نهایت شود. این موضوع بسیار مهم است که به صورت شرطی بررسی کنیم که آیا به‌روزرسانی نیاز است یا خیر و عملیات‌های asynchronous را به طور مناسب مدیریت نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Correct
componentDidUpdate(prevProps, prevState) {
if (this.props.someValue !== prevProps.someValue) {
fetchData().then(data => {
this.setState({ data });
});
}
}
// Correct componentDidUpdate(prevProps, prevState) { if (this.props.someValue !== prevProps.someValue) { fetchData().then(data => { this.setState({ data }); }); } }
// Correct
componentDidUpdate(prevProps, prevState) {
  if (this.props.someValue !== prevProps.someValue) {
    fetchData().then(data => {
      this.setState({ data });
    });
  }
}

پاک نکردن منابع در componentWillUnmount

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Incorrect
componentWillUnmount() {
clearInterval(this.intervalId);
}
// Incorrect componentWillUnmount() { clearInterval(this.intervalId); }
// Incorrect
componentWillUnmount() {
  clearInterval(this.intervalId);
}

فراموشی پاک کردن منابع، مانند intervalها یا event listenerها در متد

componentWillUnmount
componentWillUnmountمی‌تواند منجر به مشکل memory leak شود. همیشه باید مطمئن شویم که منابع را پاک کرده‌ایم تا به این ترتیب از رفتار غیرمنتظره جلوگیری نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Correct
componentWillUnmount() {
clearInterval(this.intervalId);
}
// Correct componentWillUnmount() { clearInterval(this.intervalId); }
// Correct
componentWillUnmount() {
  clearInterval(this.intervalId);
}

درک و پیاده‌سازی صحیح متدهای component lifecycle در React برای جلوگیری از خطا و اطمینان از اینکه کامپوننت‌های ما در طول چرخه عمرشان همانطور که انتظار می‌رود رفتار می‌کنند، بسیار مهم است.

نحوه اجرای مدیریت خطای سراسری

Window Error Event

event handler به نام

window.onerror
window.onerrorدر جاوااسکریپت به ما این امکان را می‌دهد که خطاهای کنترل نشده را در سطح سراسری در یک وب اپلیکیشن ثبت و مدیریت نماییم.

این event هر زمان که یک exception غیرقابل شناسایی رخ دهد راه‌اندازی می‌شود و راهی برای ثبت یا مدیریت این خطاها به صورت مرکزی را فراهم می‌کند. این یک ابزار قدرتمند برای مدیریت خطای سراسری و debugging است.

در اینجا نحوه استفاده از

window.onerror
window.onerrorبرای پیاده‌سازی مدیریت خطای سراسری را داریم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
window.onerror = function (message, source, lineno, colno, error) {
// Log the error details or send them to a logging service
console.error('Error:', message);
console.error('Source:', source);
console.error('Line Number:', lineno);
console.error('Column Number:', colno);
console.error('Error Object:', error);
// Return true to prevent the default browser error handling
return true;
};
window.onerror = function (message, source, lineno, colno, error) { // Log the error details or send them to a logging service console.error('Error:', message); console.error('Source:', source); console.error('Line Number:', lineno); console.error('Column Number:', colno); console.error('Error Object:', error); // Return true to prevent the default browser error handling return true; };
window.onerror = function (message, source, lineno, colno, error) {
  // Log the error details or send them to a logging service
  console.error('Error:', message);
  console.error('Source:', source);
  console.error('Line Number:', lineno);
  console.error('Column Number:', colno);
  console.error('Error Object:', error);

  // Return true to prevent the default browser error handling
  return true;
};

اکنون می‌خواهیم پارامترهای تابع callback

window.onerror
window.onerrorرا باهم بررسی کنیم:

  • message
    message: یک رشته که حاوی پیام خطا است.
  • source
    source: یک رشته که نشان‌دهنده URL اسکریپتی است که در آن خطا رخ داده است.
  • lineno
    lineno: یک عدد صحیح که نشان دهنده شماره خطی است که در آن خطا رخ داده است.
  • colno
    colno: یک عدد صحیح که نشان دهنده شماره ستونی است که در آن خطا رخ داده است.
  • error
    error: یک آبجکت خطا که حاوی اطلاعات اضافی درباره خطا (در صورت وجود) می‌باشد.

در handler 

window.onerror
window.onerror، می‌توانیم اقدامات مختلفی مانند ثبت جزئیات خطا در سرور، نمایش یک پیام خطای کاربر پسند یا انجام پاکسازی اضافی انجام دهیم. دستور
return true;
return true;برای جلوگیری از مدیریت خطای پیش‌فرض مرورگر استفاده می‌شود و به ما این امکان را می‌دهد که خطاها را به روشی سفارشی مدیریت نماییم.

در ادامه مثالی از استفاده از

window.onerror
window.onerrorبرای ثبت خطاها در یک سرور راه دور را داریم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
window.onerror = function (message, source, lineno, colno, error) {
// Log the error details to a remote server
const errorData = {
message,
source,
lineno,
colno,
error: error ? error.stack : null,
};
// Send errorData to a logging service (e.g., via an HTTP request)
// Return true to prevent the default browser error handling
return true;
};
window.onerror = function (message, source, lineno, colno, error) { // Log the error details to a remote server const errorData = { message, source, lineno, colno, error: error ? error.stack : null, }; // Send errorData to a logging service (e.g., via an HTTP request) // Return true to prevent the default browser error handling return true; };
window.onerror = function (message, source, lineno, colno, error) {
  // Log the error details to a remote server
  const errorData = {
    message,
    source,
    lineno,
    colno,
    error: error ? error.stack : null,
  };

  // Send errorData to a logging service (e.g., via an HTTP request)

  // Return true to prevent the default browser error handling
  return true;
};

باید این موضوع را در خاطر داشته باشیم که استفاده از

window.onerror
window.onerrorدارای محدودیت‌هایی است و ممکن است همه انواع خطاها مانند خطاهای سینتکس یا خطاهای کدهای asynchronous را دربر نگیرد.

به عنوان راه‌حل جامع‌تر رسیدگی به خطا، می‌توانیم ابزارهایی مانند بلاک‌های

try...catch
try...catch، error boundary components در React یا سرویس‌های تخصصی error tracking را در نظر بگیریم.

Promise Rejectionهای کنترل نشده:

هنگام کار با کدهای asynchronous، به ویژه با promiseها در جاوااسکریپت، رسیدگی به خطاها برای جلوگیری از promise rejectionهای کنترل نشده ضروری است.

promise rejectionهای کنترل نشده زمانی اتفاق می‌افتد که یک promise ریجکت می‌شود، اما هیچ

.catch()
.catch()یا
await
awaitمتناظری برای رسیدگی به این rejection وجود ندارد. این موضوع می‌تواند منجر به رفتار غیرمنتظره شود و debug کردن مشکلات را در برنامه ما چالش برانگیز کند.

برای پیاده‌سازی مدیریت خطای سراسری برای promise rejectionهای کنترل نشده، می‌توانیم از event

unhandledrejection
unhandledrejectionاستفاده نماییم. این event هر زمان که یک promise ریجکت شود فعال می‌گردد، اما هیچ rejection handler مرتبطی وجود ندارد.

در ادامه یک نمونه از نحوه تنظیم خطای سراسری برای promise rejectionهای کنترل نشده را بررسی می‌کنیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Setup global error handling for Unhandled Promise Rejections
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Additional logging or error handling can be added here
});
// Example of a Promise that is not handled
const unhandledPromise = new Promise((resolve, reject) => {
reject(new Error('This Promise is not handled'));
});
// Uncomment the line below to see the global error handling in action
// unhandledPromise.then(result => console.log(result));
// Example of a Promise with proper error handling
const handledPromise = new Promise((resolve, reject) => {
reject(new Error('This Promise is handled'));
});
handledPromise
.then(result => console.log(result))
.catch(error => console.error('Error:', error));
// Setup global error handling for Unhandled Promise Rejections process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); // Additional logging or error handling can be added here }); // Example of a Promise that is not handled const unhandledPromise = new Promise((resolve, reject) => { reject(new Error('This Promise is not handled')); }); // Uncomment the line below to see the global error handling in action // unhandledPromise.then(result => console.log(result)); // Example of a Promise with proper error handling const handledPromise = new Promise((resolve, reject) => { reject(new Error('This Promise is handled')); }); handledPromise .then(result => console.log(result)) .catch(error => console.error('Error:', error));
// Setup global error handling for Unhandled Promise Rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // Additional logging or error handling can be added here
});

// Example of a Promise that is not handled
const unhandledPromise = new Promise((resolve, reject) => {
  reject(new Error('This Promise is not handled'));
});

// Uncomment the line below to see the global error handling in action
// unhandledPromise.then(result => console.log(result));

// Example of a Promise with proper error handling
const handledPromise = new Promise((resolve, reject) => {
  reject(new Error('This Promise is handled'));
});

handledPromise
  .then(result => console.log(result))
  .catch(error => console.error('Error:', error));

در این مثال:

event

unhandledRejection
unhandledRejectionدر آبجکت
process
processثبت می‌شود. این event هر زمان که یک promise بدون rejection handler مربوطه reject شود، فعال می‌گردد.

یک نمونه از promise کنترل نشده (

unhandledPromise
unhandledPromise) ایجاد می‌شود. خطی که از این promise بدون
.catch()
.catch()استفاده می‌کند Uncomment شده و event
UnhandledRejection
UnhandledRejectionرا راه اندازی می‌کند.

سپس یک نمونه از promise که به درستی کنترل شده (

handledPromise
handledPromise) ایجاد می‌شود و شامل یک
.catch()
.catch()می‌باشد که رسیدگی به هرگونه rejection را برعهده دارد.

هنگامی که یک promise بدون کنترل شدن reject می‌شود، event

UnhandledRejection
UnhandledRejectionفعال می‌گردد و اطلاعات مربوط به promise reject شده، مانند خود promise و دلیل reject شدن را ثبت می‌کند.

این رویکرد به ما این امکان را می‌دهد که promise rejectionهای کنترل نشده را به صورت سراسری در برنامه خود دریافت کنیم. همینطور شناسایی و رسیدگی به مشکلات مربوط به کد asynchronous را آسان‌تر می‌کند.

همیشه باید به این موضوع توجه داشته باشیم که برای این که یک برنامه قوی و قابل اعتماد داشته باشیم، باید مدیریت صحیح خطا را برای promiseها لحاظ کنیم.

نحوه انتقال خطاها به کاربران

پیام‌های خطای کاربر پسند:

هنگامی که خطایی در برنامه رخ می‌دهد، ضروری است موضوع را به روشی که به راحتی قابل درک باشد به کاربر منتقل کنیم. برای انجام این کار بهتر است به جای نمایش جزئیات فنی، یک پیام ساده و واضح ارائه دهیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function ErrorComponent() {
return <div>Oops! Something went wrong. Please try again later.</div>;
}
function ErrorComponent() { return <div>Oops! Something went wrong. Please try again later.</div>; }
function ErrorComponent() {
  return <div>Oops! Something went wrong. Please try again later.</div>;
}

Error boundaryها:

Error boundaryهای React کامپوننت‌هایی هستند که خطاهای جاوااسکریپت را در هر نقطه از درخت کامپوننت child خود دریافت می‌کنند. آن‌ها ما را قادر می‌سازند تا خطا را به خوبی در برنامه React خود مدیریت کنیم و یک رابط کاربری fallback به کاربران نمایش دهیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, errorInfo) {
logErrorToService(error, errorInfo);
this.setState({ hasError: true });
}
render() {
if (this.state.hasError) {
return <ErrorComponent />;
}
return this.props.children;
}
}
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, errorInfo) { logErrorToService(error, errorInfo); this.setState({ hasError: true }); } render() { if (this.state.hasError) { return <ErrorComponent />; } return this.props.children; } }
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, errorInfo) {
    logErrorToService(error, errorInfo);
    this.setState({ hasError: true });
  }

  render() {
    if (this.state.hasError) {
      return <ErrorComponent />;
    }
    return this.props.children;
  }
}

کامپوننت‌هایی که ممکن است خطا ایجاد کنند را داخل کامپوننت

ErrorBoundary
ErrorBoundaryقرار می‌دهیم تا به خوبی خطاها را مدیریت نماید.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
<ErrorBoundary> <MyComponent /> </ErrorBoundary>
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

مدیریت خطاهای Asynchronous

Try-Catch  با  Async/Await:

هنگام کار با کد asynchronous، استفاده از بلاک‌های

try
tryو
catch
catchبا
async/wait
async/waitمی‌تواند به مدیریت موثرتر خطاها کمک کند.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error; // Re-throw the error to propagate it further
}
}
async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); return data; } catch (error) { console.error('Error fetching data:', error); throw error; // Re-throw the error to propagate it further } }
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching data:', error);
    throw error; // Re-throw the error to propagate it further
  }
}

()Promise.catch:

هنگامی که با promise‌ها سروکار داریم، استفاده از متد

.catch()
.catch()به ما این امکان را می‌دهد تا خطاها را به صورت مختصر مدیریت کنیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => {
// Process the data
})
.catch((error) => {
console.error('Error fetching data:', error);
// Display a user-friendly error message
alert('An error occurred while fetching data.');
});
fetch('https://api.example.com/data') .then((response) => response.json()) .then((data) => { // Process the data }) .catch((error) => { console.error('Error fetching data:', error); // Display a user-friendly error message alert('An error occurred while fetching data.'); });
fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => {
    // Process the data
  })
  .catch((error) => {
    console.error('Error fetching data:', error);
    // Display a user-friendly error message
    alert('An error occurred while fetching data.');
  });

نحوه ثبت خطاها برای انجام Debugging

ثبت خطاها برای debug کردن و بهبود پایداری برنامه React ما بسیار مهم است. می‌توانیم برای ضبط و تجزیه و تحلیل خطاها از ابزارهای توسعه‌دهنده مرورگر یا خدمات ثبت خارجی استفاده نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function logErrorToService(error, errorInfo) {
// Send the error to a logging service (e.g., Sentry, Loggly)
// Include additional information like errorInfo for better debugging
// loggingService.logError(error, errorInfo);
console.error('Logged error:', error, errorInfo);
}
function logErrorToService(error, errorInfo) { // Send the error to a logging service (e.g., Sentry, Loggly) // Include additional information like errorInfo for better debugging // loggingService.logError(error, errorInfo); console.error('Logged error:', error, errorInfo); }
function logErrorToService(error, errorInfo) {
  // Send the error to a logging service (e.g., Sentry, Loggly)
  // Include additional information like errorInfo for better debugging
  // loggingService.logError(error, errorInfo);
  console.error('Logged error:', error, errorInfo);
}

جمع‌بندی

مدیریت موثر خطا در برنامه‌های React شامل ترکیبی از اقدامات پیشگیرانه، مدیریت خطای سراسری، ارتباطات کاربرپسند و شیوه‌های debug کردن مناسب است.

با درک انواع مختلف خطاها و اجرای استراتژی‌های مناسب، می‌توانیم قابلیت اطمینان و تجربه کاربری برنامه‌های React خود را افزایش دهیم.

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

دیدگاه‌ها:

افزودن دیدگاه جدید