jquery ajax with async set to false and beforeSend registration

6 במאי 2012

תגיות: , , , ,
תגובה אחת


 


לאחרונה הגיעה אלי שאלה מעניינת,

 

אני משתמשת הרבה בקריאות סינכרוניות מקליינט לWCF.

לפני כל קריאה אני משנה את הcursor ל wait.

הבעיה היא שהוא כל כך מהיר שעוד לפני שהוא מספיק להפוך את העכבר – הוא כבר מגיע אל ה WCF ומקפיא את המסך, באופן שהעכבר נשאר כשהיה , עד שהקריאה חוזרת חזרה

(בקריאות א-סינכרוניות כמובן שזה לא קורה)

פתרתי את הבעייה הזו באמצעות

 window.setTimeout(function () { CallWCF(); }, 10);

ואז ה wait cursor מספיק להתבצע לפני שהקריאה נשלחת עקב ההשהייה.

 

האם יש פתרון מוצלח יותר במקום למלא את הקוד ב setTimeout (יש לי  קריאות רבות ל WCF)?

 

הקוד נראה כך (בערך): 

 



function click_click() {


 


 


    $.ajax({


        type: "POST",


        url: "/WebService1.asmx/HelloWorld",


        contentType: "application/json; charset=utf-8",


        dataType: "json",


        async: false,


        beforeSend: function () {


            setWaitCursor('wait');


        },


        success: function (res) {


            setWaitCursor('default');


        },


        error: function (e) {


 


        }


    });


}


 


function setWaitCursor(val) {


    $('*').css('cursor', val);


}


 


 

כעת הבעייה שנשאלת כיצד לגרום למסך לקבל את סימן ה – wait כשמפעילים את השאילתא ב – async:false.

 

בהתחלה, אמרתי שהדבר לא ייתכן – כפי שמופיע בדוקמנטצייה של jQuery (ובכל מקום אחר בגוגל) שבמידה ומדובר בקריאה סינכרונית שום דבר ב – UI לא יכול להשתנות לפני שחוזרים מהשרת – למעשה במידה וניתן היה לקרוא לקוד שהוגדר ב – beforeSend לפני הקריאה ל – $.ajax, היינו מסתפקים עם זה, הבעייה שגם הקוד שהופעל לפני הקריאה לשרת לא באמת התבצע אם היה מדובר בעבודה על ה – UI.

 

 

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

 

 

ראשית נפעיל קוד מסויים בזמן כל קריאת ajax.

נבדוק האם המפתח מעוניין להריץ קוד בזמן beforeSend.

במידה וכן נבדוק האם הקריאה הוגדרה כסינכרונית.

במידה וכן, נבטל את הקריאה לשרת.

נריץ את ה – beforeSend.

ונריץ מחדש את הקריאה לשרת ללא ה – beforeSend.

 

 

כדי לגרום להריץ קוד מסויים עבור כל קריאת jquery ajax, נשתמש ב – ajaxPrefilter, נכתוב את בלוק הקוד הבא היכן שהוא בדף.

 



$.ajaxPrefilter(function (options, originalOptions, jqXHR) {


 


    // user are register to beforeSend event and define the async property to false


    if (originalOptions.beforeSend && !originalOptions.async) {


 


        // abort the xml http request object


        jqXHR.abort();


 


        // invoke the beforeSend registerd method


        originalOptions.beforeSend();


 


        // reinvoke the ajax call after 10 milisecound (enough time for ui thread)


        setTimeout(function () {


            // remove the beforeSend event


            originalOptions.beforeSend = null;


 


            // call to server


            $.ajax(originalOptions)


        }, 10);


    }


});


 

 

כעת כל קריאה ל – ajax (בעזרת jquery) תעבור דרך קטע הקוד שצויין, במידה ונרשמו ל – beforeSend וגם הגדירו שהפעולה תהיה סינכרונית, ראשית יבוצע ה – beforeSend, ורק לאחר כ – 10 מילישניות תקרא הפונקצייה מחדש, כשכמובן הקריאה ל – beforeSend נמחקת (אחרת תהיה רקורסייה אינסופית)

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

תגובה אחת

  1. יוסי15 במאי 2012 ב 14:19

    קורץ און שארף !
    שכויעח !

    הגב