כמו שדברנו בפרק הקודם, פעולת הAJAX כוללת 3 שלבים:

  1. פעולת JS – הגדרת מאפייני הקריאה ושליחה לשרת
  2. פעולת שרת
  3. חזרה לדפדפן באמצעות JS לאחר סיום פעולת השרת

לעיתים נרצה לעצור את הקריאה בעוד השלב השני עדיין בעיצומו. כלומר – שלחנו קריאה לשרת באמצעות JS (שלב 1), כעת השרת מעבד את הנתונים (שלב 2) ועדיין לא החזיר משוב לדפדפן, וכבר אין לנו צורך בקריאה הזו, או לעיתים אפילו – אם הפעולה תושלם היא תפגע בהתנהלות העמוד, וכדו'.

במקרים כאלה ניתן לעצור את פעולת הAJAX באמצעות הדפדפן, כך שהוא לא יגיע לשלב השלישי של אירוע סיום קריאת הAJAX.

מתי צריך לעצור את הקריאה?

בדרך כלל הצורך הוא כשיש לנו רכיב שמשגר לשרת קריאות בעקבות אינטראקציה של הגולש, ויש מצב של פעולת AJAX נוספת שסותרת את הפעולה שבעיצומה, ולכן נרצה שהפעולה הנוכחית תיקטע, ובמקומה נפעיל קריאה חדשה. דוגמאות:

  • רכיב השלמה אוטומטית (= autocomplete) – יכול להיות בחיפוש וכדו'. יש לנו שדה טקסט שבו הגולש מזין טקסט. כאשר הוא הקליד נניח 3 תווים ומעלה – מתבצעת קריאה לשרת, ושליפת כל הרשומות האפשריות שרלוונטיות למה שהגולש התחיל להקליד לצורך בחירה מהירה של הגולש. לדוגמה הגולש כתב "ירו" – יחזרו לו "ירושלים", "אירועים" וכדו'.
    כאשר הגולש ממשיך להקליד, או לחילופין – מוחק את מה שהוקלד ומקליד טקסט שונה – צריך לעצור את הקריאה הנוכחית ("ירו") ובמקומה לשלוח לשרת את הסטרינג הנוכחי כדי להביא תוצאות רלוונטיות חדשות.
  • רכיב סינון – לדוגמה באתר שמציג הרבה מוצרים לרכישה. בעמוד המוצרים הראשי יש תצוגה של המוצרים כולם, וסיידבר עם מסננים שונים – לפי צבע, לפי מידה וכדו'. הגולש סימן צבע "ירוק", ומיד מסמן גם "מידות 0-6 חודשים". כאשר הגולש סימן את "ירוק" – התבצעה קריאת AJAX לשרת, עם הפרמטר "ירוק", כך שיוצגו רק מוצרים ירוקים, אבל לאחר שהגולש בחר גם מידה – מיד צריכה להתבטל הקריאה הקודמת כי היא אינה רלוונטית, ובמקומה צריכה להתבצע קריאה לשרת עם הפרמטרים "ירוק" + "מידות 0-6 חודשים" כדי להביא רק בגדים מתאימים.
  • מקומות שיש לנו פונקציונליות של "טען עוד" בעת גלילה לסוף הרשימה, וכן יש סינון או מיון לפריטים.
    אם נשתמש בדוגמת האתר למכירת פריטי לבוש – בטעינת העמוד נטענו לי רק ה20 פריטים הראשונים, וכאשר אגלול קרוב לתחתית הרשימה – תקרה קריאת AJAX לטעינת פריטים נוספים לעמוד. נניח שגללתי ומתבצעת קריאת הAJAX לקבלת 20 הפריטים הבאים, וטרם היא הסתיימה סימנתי כפתור רדיו למיון את הפריטים לפי פופולריות. כעת הפריטים שאמורים להגיע תכף בשביל ה"טען עוד" – כבר אינם נדרשים, ובמקומם אמורים להגיע 20 הפריטים הפופולריים ביותר.

למה לעצור את הקריאה? למה לא להסתפק בקריאה חוזרת?

  • אם תגענה התוצאות אחת אחרי השניה, ותודפסנה למסך במיידי אחת אחרי השניה – עשוי להיות ריצוד לגולש
  • במקרה הראשון של רכיב השלמה אוטומטית – במידה וכתבתי "ירו" ואז מחקתי וכתבתי "כגדש" – אם קודם תגענה התוצאות של "ירו" – הן כבר אינן רלוונטיות למה שהקלדתי. למה שהן תוצגנה? גם אם זה לרגע?
  • במקרים רבים, הקריאה השניה עשויה להסתיים מהר יותר מאשר הקריאה הראשונה, ואז הגולש יישאר עם התוצאות של הקריאה הראשונה במקום עם התוצאות שרלוונטיות לו. בדוגמה השניה שנתנו – ישנם 50 בגדים שמסומנים ב"ירוק" ונניח שלוקח לשרת שתי שניות לרוץ עליהם בלולאה ולייצר HTML שלהם כדי להחזיר לדפדפן. לעומת זאת לסינון של גם ב"ירוק" וגם ב"מידות 0-6 חודשים" יש רק 4 פריטים מתאימים, וייקח לשרת חצי שניה בלבד לרוץ עליהם ולהחזיר HTML לגולש.
    במקרה כזה, הגולש יקבל קודם את התוצאות הנכונות – 4 פריטים התואמים את הסינון הנוכחי (שתי מסננים), ורק אחר כך יקבל את ה50 פריטים המסומנים ב"ירוק", כך שהוא יישאר עם תוצאות שאינן רלוונטיות כלל למה שהוא חיפש.

כמובן שאפשר למנוע את התופעות הללו באמצעות flags שונים של האם יש פעולה שקורית עכשיו אז אל תדפיס את התוצאות הנוכחיות וכדו', אבל בשביל מה?! אין טעם לבצע את זה, אם אפשר בקלות לעצור את הקריאה שאינה רלוונטית יותר, ולהמנע מבעיות.

תחביר הפונקציה abort()

נשתמש בפונקצית jQuery שנקראת abort. את הפונקציה יש להריץ על אובייקט הXHR של הקריאה.

בפרק הקודם דברנו על אפשרות לשמירת נתוני קריאת הAJAX לתוך משתנה. תזכורת, כך כותבים את זה:

var xhr = jQuery.ajax({
    url: ....,
    method: 'POST'
});

כעת במקרה שנרצה לעצור את קריאת הAJAX בעודה קורית נוסיף שאלה, אם כבר התבצעה קריאה קודמת, ואם היא לא הסתיימה עדיין – נעצור אותה ורק אז נפעיל קריאה חדשה. הבדיקה האם הקריאה הקודמת הסתיימה או לא אינה חובה. אתן דוגמאות איתה ובלעדיה.

שימו ♥, מאחר ואנחנו שואלים את המשתנה xhr שלנו לפני קריאת הAJAX עצמה – נצהיר עליו גם קודם. אחרת בפעולת הAJAX הראשונה תקפוץ לנו שגיאה שאחנו שואלים על משתנה שאינו קיים.

קוד לדוגמה עבור שאלה האם קיימת קריאה קודמת:

var xhr;

if(xhr)
    xhr.abort();

xhr = jQuery.ajax({
   ....
});

קוד לדוגמה עבור שאלה האם הקריאה הקודמת טרם הסתיימה:

var xhr;

if(xhr && xhr.readyState != 4) 
    xhr.abort(); 
xhr = jQuery.ajax({ 
    ....
});

הפרמטר xhr.readyState יחזיר לנו מה מצב הקריאה. תוכלו לקרוא כאן בהרחבה על הפרמטר הזה. לעניינינו – כאשר readyState שווה ל4 – סימן שהקריאה הסתיימה כבר, ובמקרה כזה אין לנו צורך לעצור אותה. לכן השאלה שרשמנו בקוד שלנו הוא אם הפרמטר שונה מ4 – כלומר, הפעולה עדיין בעיצומה.

כפי שניתן לראות – שאלנו קודם אם המשתנה xhr אינו ריק, כי אם זו הפעם הראשונה שרוצים להפעיל קריאת AJAX והמשתנה הזה עדיין ריק – אם נשאל על הפרמטר readyState של משתנה ריק – שוב תקרה שגיאת JS, לכן נבצע את השאלה הזו באופן הזה.

כמה הערות לסיום

  • כאשר אנחנו קוטעים קריאת AJAX באמצעות abort – לא קטענו את הפעולה בשרת, אלא רק בטלנו את הקישור שלה בדפדפן. כלומר – מבחינת הJS שבדפדפן הקריאה יותר לא מוכרת, אבל השרת עדיין עושה מה שבקשנו ממנו לעשות. כלומר – אם אנחנו רוצים לקטוע את קריאת הAJAX כדי להוריד מעמסה מהשרת, שלא יצטרך לעבוד על קריאה שאינה רלוונטית – לא השגנו את המטרה הזו.
  • האובייקט שנכנס לנו לתוך xhr בדוגמאות שנתנו הוא אובייקט של JS ולא דווקא של jQuery. תוכלו להפעיל עליו פונקציונליות מלאה של JavaScript ולא רק פונקציות של jQuery.

 

זה הכל לבינתיים, לדעתי די הקפנו את נושא קריאת הAJAX באמצעות jQuery.

בהצלחה רבה!

כתיבת תגובה

האימייל לא יוצג באתר.