Wednesday, February 27, 2008

How to abort asynchronous ajax method calls

Kamal Balwani asked for my help on the blog chat today and asked for the solution for a really annoying issue. He was opening a window when pressing a button on an ASP.Net page and that window used web services to request data from the server repeatedly. The problem was when the window was closed and FireFox (the error did not appear on Internet Explorer) showed a 'Sys is not defined' error on this javascript line: _this._webRequest.completed(Sys.EventArgs.Empty);.

It was a silly error, really. There was this javascript object Sys.Net.XMLHttpExecutor and it had a function defined called _onReadyStateChange where a completed function received Sys.EventArgs.Empty as an argument. At that time, though, the page was unloaded as well as any objects defined in it. I consider this a FireFox bug, as any javascript function should not try to access an object that was unloaded already.

Anyway, going through the Microsoft Ajax library is a nightmare. I am sure they had clear patterns in mind when they designed it this way but for me it was a long waste of time trying to get my head around it. Finally I've decided that the only solution here was to abort the last Ajax request and so I've reached these two posts:

Cancel a Web Service Call in Ajax
How to cancel the call to web service.

Bottom line, you need to use the abort function on a WebRequestExecutor object which one can get from using the get_executor function on a WebRequest object which should be returned by a scriptmethod call.

But you see, when you execute TestService.MyMethod you get no return value. What you need to do is use TestService._staticInstance.MyMethod which returns the WebRequest object required! Good luck figuring that out without Googling for it.

From then on the ride was smooth: add an array of web requests and at the window.onbeforeunloading event, just abort them all.

Here is the code for the popup window:

<body onload = "runMethod();" onbeforeunload = "KillRequests();">

function runMethod() {
   if (!window._webRequests) window._webRequests = Array();
      = TestService._staticInstance
        .MyMethod(OnSuccess, OnTimeout);

function OnSuccess(result) {
   //do something with the result
   setTimeout(runMethod, 500);

function OnTimeout(result) {
   setTimeout(runMethod, 500);

function KillRequests() {
   if (!window._webRequests) return;
   for (var c = 0; c < window._webRequests.length; c++) {
      if (window._webRequests[c]) {
         var executor = window._webRequests[c].get_executor();
         if (executor.get_started()) executor.abort();


LEO said...

Hey its me kamal balwani , man really thanks for such a Gr8 Help.. it was just flash of brilliance ....

Anonymous said...


I am getting "Sys is not defined" error in firefox.When i am trying to login by pressing enter key in password textbox.It works fine in IE7 and firefox in my local machine.
But i get this error when i try to login from another system in my network(LAN).
In my default page i am calling many webserices.Is this error because of that.
Can you please help me how to solve this problem.


Trevor Feldman said...

Thank you – you are a lifesaver! Your information helped me solve the problem (after almost a day of searching) of why my app was hanging up IE 6 when a popup window was closed before pending AJAX requests were completed.