שימוש ב-Abort כדי לבטל קריאה אסינכרונית לשרת

פעמים רבות אנחנו מבצעים פעולות מורכבות בשרת מסד הנתונים שמעסיק את השרת הרבה מאד זמן. לדוגמה, חיפושים בצד הלקוח (Client) באמצעות שימוש בLike בשרת.
חיפושים כאלה נפוצים כמעט בכל סוג של אתר, למשל חיפוש החברים בפייסבוק שמציג רשימה מקדימה של החברים תוך כדי הקלדת שם החבר.

בדרך כלל תהליך החיפוש מבוצע כך:
  1. משתמש מקליד אות בתיבת טקסט
  2. באמצעות JavaScript מבוצעת קריאה אסינכרונית (AJAX) לשרת האינטרנט לצורך אחזור רשימת החברים ששמם מכיל את המילה שבתיבת הטקסט.
  3. האפליקציה בשרת מקבלת את הקריאה (Request) וקוראת לשרת מסד הנתונים (SQL) כדי לקבל את המידע
  4. שרת מסד הנתונים מבצע את החיפוש ומחזיר חזרה טבלה עם תוצאות החיפוש
  5. האפליקציה בשרת מעצבת את הנתונים, בדרך כלל לפורמט JSON, ומחזירה תשובה (Response) ללקוח - הדפדפן
  6. הדפדפן קולט את הנתונים, מעבד אותם ומציג אותם למשתמש ברשימה מסודרת.
בדרך כלל התהליך שלמעלה מתבצע בשברירי שניה ולכן המשתמש הסופי לא מרגיש בכל התהליך, וכאן היתרון של שימוש בAJAX. 

באתרים קטנים התהליך הנ"ל עובד נפלא ולא תרגישו שחסר משהו בתהליך. אבל, התהליך מתחיל להסתבך ככל שמספר המשתמשים או זמן הביצוע של השאילתה גדל, ואני יסביר:
בשלב (1) שלמעלה כאשר המשתמש מקליד הוא בדרך כל לא עוצר באות הראשונה וממתין לתוצאה אלא ממשיך להקליד הלאה את שם החבר המלא שברצונו לחפש. כתוצאה מכך יתכן מצב שבו נפתחו 5 קריאות אסינכרוניות לשרת עבור כל אות שהוא הקליד בעוד שרק הקריאה האחרונה רלוונטית לנו כיון שהיא זו שתחזיר את התוצאות של המילה כפי שהיא קיימת בתיבת הטקסט.

כיון שכך ברור שהתהליך למעלה לא מושלם ויש לתקן אותו. לשם כך נוסיף שלב נוסף אחרי שלב (1) והתהליך יראה כך:
  1. משתמש מקליד אות בתיבת טקסט
  2. אם כבר קיימת קריאה קודמת לשרת - מבטלים אותה על ידי שימוש בפונקציה XMLHttpRequest.abort
  3. באמצעות JavaScript מבוצעת קריאה אסינכרונית (AJAX) לשרת האינטרנט לצורך אחזור רשימת החברים ששמם מכיל את המילה שבתיבת הטקסט.
  4. האפליקציה בשרת מקבלת את הקריאה (Request) וקוראת לשרת מסד הנתונים (SQL) כדי לקבל את המידע
  5. שרת מסד הנתונים מבצע את החיפוש ומחזיר חזרה טבלה עם תוצאות החיפוש
  6. האפליקציה בשרת מפרמטת את הנתונים, בדרך כלל לפורמט JSON, ומחזירה תשובה (Response) ללקוח - הדפדפן
  7. הדפדפן קולט את הנתונים, מעבד אותם ומציג אותם למשתמש ברשימה מסודרת.
כעת הכל נראה תקין ומתוחזק היטב.
אבל, אם נבדוק את העומסים על השרת נגלה ששום דבר לא השתנה השרת עדיין עמוס כמו קודם. הסיבה לכך היא שאמנם ביטלנו את הקריאה לשרת אבל השרת לא מודע לזה שעזבנו אותו והוא ממשיך לטפל בקריאה עד לסיומה. זה נובע מהעובדה שהפונקציה Abort אינה מבטלת את התהליך בשרת, היא רק מנתקת את הקשר עם השרת ולא ממתינה יותר לתשובה, אבל בינתיים השרת לא יודע מזה עד שהוא יסיים את הפעולה וינסה להחזיר תשובה ואז הוא יגלה שהחיבור נותק. אם כך הקריאה ל-Abort אינה מספיקה וצריך להוסיף ביטול גם של התהליך בשרת. לשם כך נוסיף מספר שלבים נוספים לתהליך:

  1. משתמש מקליד אות בתיבת טקסט
  2. אם כבר קיימת קריאה קודמת לשרת - מבטלים אותה על ידי קריאה לפונקציה XMLHttpRequest.Abort
  3. באמצעות JavaScript מבוצעת קריאה אסינכרונית (AJAX) לשרת האינטרנט לצורך אחזור רשימת החברים ששמם מכיל את המילה שבתיבת הטקסט.
  4. האפליקציה בשרת מקבלת את הקריאה (Request) 
  5. האפליקציה קוראת לשרת מסד הנתונים (SQL) כדי לקבל את המידע. הקריאה מבוצעת בתהליך (Thread) נפרד או על ידי שימוש בפונקציות האסינכרוניות של ה-Command למשל "BeginExecuteNonQuery".
  6. במהלך ההמתנה לתשובה משרת ה-SQL בודקים באופן מחזורי את ה-Response.IsClientConnected. במידה והוא FALSE קוראים ל-Command.Cancel ולאחר מכן Response.End כדי לבטל את כל התהליכים שרצים על השרת
  7. שרת מסד הנתונים מבצע את החיפוש ומחזיר חזרה טבלה עם תוצאות החיפוש
  8. האפליקציה בשרת מפרמטת את הנתונים, בדרך כלל לפורמט JSON, ומחזירה תשובה (Response) ללקוח - הדפדפן
  9. הדפדפן קולט את הנתונים, מעבד אותם ומציג אותם למשתמש ברשימה מסודרת.
ולכן כאשר המשתמש מקליד אותיות השרת יתחיל לטפל את בקריאה הראשונה אבל כיון שהמשתמש מקליד מיד אות שנייה הקריאה הראשונה מתבטלת על ידי Abort (שלב 2) כתוצאה מכך השרת מבטל את הטיפול בקריאה (שלב 6) ובכך מתפנה לטפל בקריאה הבאה - וכך הלאה מאות לאות.



תגובות

רשומות פופולריות