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

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

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

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

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

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

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

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

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

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

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

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

  • ما هو السلوك التلقائي إذا تعذّر على خدمة مشاركة الفيديو معالجة المثال المقدَّم؟
  • ماذا يتوقع المستخدم أن يحدث في المثال؟
  • كيف يمكننا تحسين هذه العملية؟
الإجراء يبدأ المستخدم بتحميل ملف الفيديو غير الصحيح. بعد ذلك، في منتصف عملية التحميل، يحدّد المستخدم ملف الفيديو الصحيح المطلوب تحميله.
ما يحدث تلقائيًا يستمر تحميل الملف الأصلي في الخلفية بينما يتم تحميل الملف الجديد في الوقت نفسه.
ما يتوقعه المستخدم يتوقّع المستخدم أن يتوقف التحميل الأصلي حتى لا يتم إهدار أيّ عرض نطاق إضافي للإنترنت.
ما الذي يمكن تحسينه تلغي JavaScript طلب الجلب للملف الأصلي قبل بدء تحميل الملف الجديد.
الإجراء فقدان المستخدم الاتصال بالإنترنت أثناء تحميل الفيديو
ما يحدث تلقائيًا يبدو أنّ شريط تقدّم التحميل لا يزال متوقفًا عند نسبة %50. وفي النهاية، تنتهي مهلة Fetch API ويتم تجاهل البيانات التي تم تحميلها. عند استعادة الاتصال بالإنترنت، على المستخدم إعادة تحميل ملفه.
ما يتوقعه المستخدم يتوقع المستخدم أن يتم إعلامه عندما يتعذّر تحميل ملفه، ويتوقع أن يستأنف التحميل تلقائيًا عند بلوغ نسبة% 50 من التحميل بعد إعادة الاتصال بالإنترنت.
ما الذي يمكن تحسينه تُعلم صفحة التحميل المستخدم بمشاكل الاتصال بالإنترنت، وتطمئنه بأنّه سيتم استئناف التحميل عند استئناف الاتصال بالإنترنت.
الإجراء لا يمكن للموقع الإلكتروني لمشاركة الفيديوهات معالجة اسم ملف يتضمّن مسافة. بدلاً من "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 ردًا غير متوقّع؟
  • ماذا يحدث إذا انقطع اتصال المستخدم بالإنترنت؟

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