Cancel dojo XHR in progress

Posted by Mike on Sep 3rd, 2008

Often you run across a use-case where you want users to be able to fire off an XMLHttpRequest while another is ongoing.  Sometimes, the requests are independent and affect independent objects as a result.   But othertimes, the callback functions from the two could be affecting the same event.

For example, imagine you have a list of cars in your inventory.  When a user clicks on one of the cars, a request is shot back to determine price, color, inventory stock, and description before displaying it.  If a user clicks on the VW Jetta, then quickly changes their mind and clicks on the Mazda 3, what would happen?  We’d expect the VW Jetta to be forgotten about and the data to be displayed for the Mazda.  But with all the randomness on the internet, if the 2nd request was quick to be returned from the server, while the 1st got delayed, a poorly designed app would display the Mazda, later receive the callback from the Jetta and overwrite the good results with the one the user had already forgotten about.

We could imagine 2 scenarios for how to stop the possibility of timing issues producing inconsistencies.

  1. Block all future car clicks until the initial car click is loaded.  Ugh.  Terrible user experience.
  2. When a car is clicked, see if any pending cars are being queried.  If so, cancel them, and query the new one.

How do we make this happen in Dojo 1.0 world?  Simple.  Use the cancel() method given back by the deferred xhr object.

1
2
3
4
5
6
this.doSingleXhr = function() {
    if (this._xhr) {
       this._xhr.cancel();
    }
    this._xhr = dojo.xhrGet(args);
}

Almost done.  The one hangup you might see is that the cancel() method does trigger the error() callback if you have one defined in your xhrGet.  Luckily, we can inspect the dojoType of the args given to the callback to determine if it’s the result of a cancel and ignore it.

1
2
3
4
5
6
7
8
9
10
11
12
this.doSingleXhr = function() {
    if (this._xhr) {
        this._xhr.cancel();
    }
    this._xhr = dojo.xhrGet({
        ...
        error: function(args) {
            if (args.dojoType=='cancel') { return; }
            handleError();
        }
    });
}
  • Twitter
  • Facebook
  • StumbleUpon
  • Google Reader
  • Reddit
  • Share/Bookmark

4 Responses

  1. Fred Böhni Says:

    Thanks a bunch, exactly what I was looking for.
    (Except that the function was hiding somewhere deep, but “args.dojoType==’cancel’” fixed it :)
    FB

  2. Joe Says:

    if you specify
    dojo.xhrGet({
    … failOk: true …
    you get rid of the error log that otherwise occurs;
    the error: function… will be executed anyways

  3. Ashutosh Joshi Says:

    I think this this must be…

    if(response.dojoType == “cancel”){
    //The request was canceled by some other JavaScript code.
    console.debug(“Request canceled.”);
    }else if(response.dojoType == “timeout”){
    //The request took over 5 seconds to complete.
    console.debug(“Request timed out.”);
    }else{
    //Some other error happened.
    console.error(response);
    }

  4. Homepage Says:

    Like I said, if you have no better options, this is a pretty good
    option. You strongly need the ability to stay motivated day
    in and day out when you are not seeing any results yet.
    Choose a popular site for your purpose, because they are visited by
    more number of people.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.