تنفيذ معالجة الأخطاء عند استخدام واجهة برمجة تطبيقات الجلب

تعرض هذه المقالة بعض أساليب معالجة الأخطاء عند العمل باستخدام واجهة برمجة تطبيقات الجلب. تتيح لك واجهة برمجة التطبيقات Fetch API إرسال طلب إلى مورد شبكة عن بُعد. عند إجراء اتصال عبر شبكة عن بُعد، تتعرض صفحة الويب لمجموعة متنوعة من الأخطاء المحتملة في الشبكة.

توضّح الأقسام التالية الأخطاء المحتمَلة وكيفية كتابة رمز برمجي يقدّم مستوى معقولًا من الوظائف التي يمكنها مقاومة الأخطاء وظروف الشبكة غير المتوقّعة. يحافظ الرمز المتين على رضا المستخدمين ويحافظ على مستوى عادي من الخدمة لموقعك الإلكتروني.

يصف هذا القسم سيناريو ينشئ فيه المستخدم فيديو جديدًا باسم "My Travels.mp4" ثم يحاول تحميل الفيديو إلى موقع إلكتروني لمشاركة الفيديوهات.

عند استخدام ميزة "الجلب"، من السهل مراعاة المسار الصحيح الذي يحمِّل فيه المستخدم الفيديو بنجاح. ومع ذلك، هناك مسارات أخرى ليست سلسة، ولكن على مطوّري الويب التخطيط لها. يمكن أن تحدث هذه المسارات (غير المرغوب فيها) بسبب خطأ من المستخدم أو بسبب ظروف بيئية غير متوقّعة أو بسبب خطأ في الموقع الإلكتروني لمشاركة الفيديوهات.

أمثلة على أخطاء المستخدمين

  • يحمّل المستخدم ملف صورة (مثل JPEG) بدلاً من ملف فيديو.
  • يبدأ المستخدم في تحميل ملف الفيديو الخاطئ. بعد ذلك، يحدد المستخدم ملف الفيديو الصحيح للتحميل، وذلك من خلال عملية التحميل.
  • ينقر المستخدم عن طريق الخطأ على "إلغاء التحميل" أثناء تحميل الفيديو.

أمثلة على التغيّرات البيئية

  • انقطاع الاتصال بالإنترنت أثناء تحميل الفيديو
  • تتم إعادة تشغيل المتصفّح أثناء تحميل الفيديو.
  • إعادة تشغيل خوادم الموقع الإلكتروني لمشاركة الفيديو أثناء تحميل الفيديو

أمثلة على الأخطاء في الموقع الإلكتروني لمشاركة الفيديوهات

  • لا يمكن للموقع الإلكتروني لمشاركة الفيديوهات معالجة اسم ملف يتضمّن مسافة. وبدلاً من "My Travels.mp4"، يتم توقع اسم مثل "My_Travels.mp4" أو "MyTravels.mp4".
  • لا يمكن للموقع الإلكتروني لمشاركة الفيديوهات تحميل فيديو يتجاوز الحد الأقصى المسموح به لحجم الملف.
  • لا يتيح الموقع الإلكتروني لمشاركة الفيديوهات برنامج ترميز الفيديو في الفيديو الذي تم تحميله.

هذه الأمثلة يمكن أن تحدث في العالم الحقيقي. ربما صادفت أمثلة مماثلة في الماضي. لنختار مثالاً واحدًا من كل فئة من الفئات السابقة ونناقش النقاط التالية:

  • ما هو السلوك التلقائي إذا لم تتمكّن خدمة مشاركة الفيديو من معالجة المثال المقدَّم؟
  • ماذا يتوقع المستخدم أن يحدث في المثال؟
  • كيف يمكننا تحسين هذه العملية؟
الإجراء يبدأ المستخدم في تحميل ملف الفيديو الخاطئ. بعد ذلك، يحدد المستخدم ملف الفيديو الصحيح للتحميل، وذلك من خلال عملية التحميل.
ما يحدث تلقائيًا يستمر تحميل الملف الأصلي في الخلفية بينما يتم تحميل الملف الجديد في الوقت نفسه.
ما يتوقعه المستخدم يتوقع المستخدم أن يتوقف التحميل الأصلي كي لا يهدر المزيد من معدل نقل بيانات الإنترنت.
ما الذي يمكن تحسينه تلغي JavaScript طلب الجلب للملف الأصلي قبل بدء تحميل الملف الجديد.
الإجراء فقدان المستخدم الاتصال بالإنترنت أثناء تحميل الفيديو
ما يحدث تلقائيًا يبدو أنّ شريط تقدّم التحميل متوقّف عند نسبة 50%. وفي النهاية، تنتهي مهلة Fetch API ويتم تجاهل البيانات المحمَّلة. عند استعادة الاتصال بالإنترنت، يتعين على المستخدم إعادة تحميل الملف.
ما يتوقعه المستخدم ويتوقع المستخدم أن يتم إشعاره عندما يتعذر تحميل الملف، ويتوقع أن يتم استئناف التحميل تلقائيًا عند اتصاله بالإنترنت مرة أخرى.
ما الذي يمكن تحسينه تُعلم صفحة التحميل المستخدم بمشاكل الاتصال بالإنترنت، وتطمئنه بأنّه سيتم استئناف التحميل عند استئناف الاتصال بالإنترنت.
الإجراء لا يمكن للموقع الإلكتروني لمشاركة الفيديوهات معالجة اسم ملف يتضمّن مسافة. بدلاً من "My Travels.mp4"، يتوقع أسماء مثل "My_Travels.mp4" أو "MyTravels.mp4".
ما يحدث تلقائيًا على المستخدم الانتظار إلى أن يكتمل التحميل بالكامل. بعد تحميل الملف وظهور "100%" في شريط التقدّم، يعرض شريط التقدّم الرسالة "يُرجى إعادة المحاولة".
ما يتوقعه المستخدم يتوقع المستخدم أن يتم إعلامه بالقيود المفروضة على أسماء الملفات قبل بدء عملية التحميل، أو خلال أول ثانية من عملية التحميل على الأقل.
ما الذي يمكن تحسينه من الأفضل أن تتيح خدمة مشاركة الفيديو استخدام أسماء ملفات تحتوي على مسافات. وتشمل الخيارات البديلة إشعار المستخدم بالقيود المفروضة على أسماء الملفات قبل بدء عملية التحميل. أو يجب أن ترفض خدمة مشاركة الفيديو عملية التحميل مع عرض رسالة خطأ مفصّلة.

التعامل مع الأخطاء باستخدام واجهة برمجة التطبيقات Fetch API

يُرجى العِلم أنّ أمثلة الرموز البرمجية التالية تستخدِم await (توافق المتصفّح) من المستوى الأعلى لأنّ هذه الميزة يمكن أن تبسِّط رمزك البرمجي.

عندما تُعرِض واجهة برمجة التطبيقات Fetch API أخطاء

يستخدم هذا المثال عبارة كتلة try/catch لرصد أي أخطاء يتم طرحها داخل كتلة try. على سبيل المثال، إذا تعذّر على Fetch API جلب المورد المحدّد، يتم طرح خطأ. ضمن قالب catch مثل هذا، احرص على تقديم تجربة مفيدة للمستخدم. إذا تم عرض مؤشر تقدم، وهو واجهة مستخدم شائعة تمثّل نوعًا من التقدّم، للمستخدم، يمكنك اتّخاذ الإجراءات التالية ضمن عنصر catch:

  1. أزِل مؤشر التقدم من الصفحة.
  2. قدِّم رسائل مفيدة توضّح المشكلة والخيارات المتاحة للمستخدم.
  3. استنادًا إلى الخيارات المتاحة، اعرض زر "إعادة المحاولة" على المستخدم.
  4. في الخلفية، أرسِل تفاصيل الخطأ إلى خدمة تتبُّع الأخطاء أو إلى الخلفية. يسجِّل هذا الإجراء الخطأ ليتمكّن من تشخيصه في مرحلة لاحقة.
try {
  const response = await fetch('https://website');
} catch (error) {
  // TypeError: Failed to fetch
  console.log('There was an error', error);
}

في مرحلة لاحقة، أثناء تشخيص الخطأ الذي سجّلته، يمكنك كتابة حالة اختبار لرصد هذا الخطأ قبل أن يلاحظ المستخدمون حدوث مشكلة. استنادًا إلى الخطأ، يمكن أن يكون الاختبار اختبار وحدة أو اختبار دمج أو اختبار قبول.

عندما يشير رمز حالة الشبكة إلى خطأ

يُجري مثال الرمز البرمجي هذا طلبًا إلى خدمة اختبار HTTP تستجيب دائمًا برمز حالة HTTP‏ 429 Too Many Requests. من المثير للاهتمام أنّ الردّ لا يصل إلى مجموعة catch. لا يعرض رمز الحالة 404، من بين رموز حالة أخرى معيّنة، خطأ في الشبكة، بل يتم حلّه بشكلٍ طبيعي.

للتحقّق من نجاح رمز حالة HTTP، يمكنك استخدام أيّ من الخيارات التالية:

  • استخدِم السمة Response.ok لتحديد ما إذا كان رمز الحالة في النطاق من 200 إلى 299.
  • استخدِم السمة Response.status لتحديد ما إذا كان الردّ ناجحًا.
  • استخدِم أي بيانات وصفية أخرى، مثل Response.headers، لتقييم ما إذا كانت الاستجابة ناجحة.
let response;

try {
  response = await fetch('https://httpbin.org/status/429');
} catch (error) {
  console.log('There was an error', error);
}

// Uses the 'optional chaining' operator
if (response?.ok) {
  console.log('Use the response here!');
} else {
  console.log(`HTTP Response Code: ${response?.status}`)
}

من أفضل الممارسات العمل مع أفراد مؤسستك وفردك في الفريق لفهم رموز حالة استجابة HTTP المحتملة. يمكن لمطوّري الخلفية وعمليات المطوّرين ومهندسي الخدمات تقديم إحصاءات فريدة في بعض الأحيان حول الحالات القصوى المحتمَلة التي قد لا تتوقّعها.

عند حدوث خطأ في تحليل ردّ الشبكة

يوضّح مثال الرمز البرمجي هذا نوعًا آخر من الأخطاء التي يمكن أن تحدث عند تحليل نص الاستجابة. توفّر واجهة Response طرقًا ملائمة لتحليل أنواع مختلفة من البيانات، مثل النص أو JSON. في الرمز التالي، يتم إرسال طلب شبكة إلى خدمة اختبار HTTP التي تعرض سلسلة HTML كنص الاستجابة. ومع ذلك، يتم إجراء محاولة لتحليل نص الاستجابة باعتباره JSON، ما يؤدي إلى ظهور خطأ.

let json;

try {
  const response = await fetch('https://httpbin.org/html');
  json = await response.json();
} catch (error) {
  if (error instanceof SyntaxError) {
    // Unexpected token < in JSON
    console.log('There was a SyntaxError', error);
  } else {
    console.log('There was an error', error);
  }
}

if (json) {
  console.log('Use the JSON here!', json);
}

يجب تجهيز الرمز لتضمين مجموعة متنوعة من تنسيقات الردود، والتأكّد من أنّ الاستجابة غير المتوقعة لن تؤدي إلى إيقاف صفحة الويب لدى المستخدم.

لنفترض السيناريو التالي: لديك مورد بعيد يعرض استجابة JSON صالحة، ويتم تحليلها بنجاح باستخدام الطريقة Response.json(). قد يحدث تعطّل في الخدمة. بعد الانتهاء، يتم عرض 500 Internal Server Error. وإذا لم يتم استخدام أساليب مناسبة للتعامل مع الأخطاء أثناء تحليل JSON، قد يؤدي ذلك إلى إيقاف الصفحة لدى المستخدم بسبب حدوث خطأ لم تتم معالجته.

الحالات التي يجب فيها إلغاء طلب الشبكة قبل اكتماله

يستخدم مثال الرمز هذا AbortController لإلغاء طلب أثناء الطيران. الطلب الجاري هو طلب شبكة بدأ ولكن لم يكتمل.

قد تختلف السيناريوهات التي قد تحتاج فيها إلى إلغاء طلب قيد التنفيذ، ولكن يعتمد ذلك في النهاية على حالة الاستخدام والبيئة. يوضّح الرمز التالي كيفية تمرير AbortSignal إلى Fetch API. يتم إرفاق AbortSignal بعنصر AbortController، ويتضمن AbortController طريقة abort()، ما يشير إلى المتصفّح أنّه يجب إلغاء طلب الشبكة.

const controller = new AbortController();
const signal = controller.signal;

// Cancel the fetch request in 500ms
setTimeout(() => controller.abort(), 500);

try {
  const url = 'https://httpbin.org/delay/1';
  const response = await fetch(url, { signal });
  console.log(response);
} catch (error) {
  // DOMException: The user aborted a request.
  console.log('Error: ', error)
}

الخاتمة

يتمثل أحد الجوانب المهمة للتعامل مع الأخطاء في تحديد الأجزاء المختلفة التي يمكن أن تحدث بشكل خاطئ. تأكَّد من توفُّر بديل مناسب للمستخدم في كل سيناريو. في ما يتعلّق بطلب الجلب، اطرح على نفسك أسئلة مثل:

  • ماذا يحدث إذا تعطّل الخادم المستهدَف؟
  • ماذا يحدث إذا تلقّى Fetch ردًا غير متوقّع؟
  • ماذا يحدث إذا فشل اتصال المستخدم بالإنترنت؟

استنادًا إلى مدى تعقيد صفحة الويب، يمكنك أيضًا رسم مخطّط بياني يصف الوظائف وواجهة المستخدم لسيناريوهات مختلفة.