יישום טיפול בשגיאות במהלך שימוש ב-Fetch API

במאמר הזה נסביר על כמה גישות לטיפול בשגיאות בעבודה עם 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 ברמה העליונה (תמיכה בדפדפנים) כי התכונה הזו יכולה לפשט את הקוד.

כשממשק ה-API לאחזור מציג שגיאות

בדוגמה הזו נעשה שימוש בהצהרה של try/catch block כדי לתפוס שגיאות שמתרחשות בתוך הבלוק try. לדוגמה, אם ממשק ה-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 שמגיב תמיד עם קוד הסטטוס 429 Too Many Requests של HTTP. באופן מעניין, התגובה לא מגיעה לבלוק 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 כולל method 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 מקבל תגובה לא צפויה?
  • מה קורה אם החיבור לאינטרנט של המשתמש נכשל?

בהתאם למורכבות דף האינטרנט שלכם, תוכלו גם לשרטט תרשים זרימה שמתאר את הפונקציונליות ואת ממשק המשתמש בתרחישים שונים.