pspahn
pspahn

Reputation: 2790

jQuery - Stop ajax requests

(I really didn't know how to title this, feel free to suggest an edit)

Consider the following sample html:

<div class="grid">
    <div class="item"><span class="icon"></span></div>
    <div class="item"><span class="icon"></span></div>
    <div class="item"><span class="icon"></span></div>
    <div class="item"><span class="icon"></span></div>
    <div class="item"><span class="icon"></span></div>
</div>

Attached to each .icon is some jQuery:

<script type="text/javascript">
    jQuery('.icon').click(function(){
        runAjaxStuff();
        displayNewContent();
    })
</script>

In a nutshell, each time a user clicks an .icon, the corresponding parent .item will perform an AJAX request and finish by displaying additional .item content on the page.

If a user, in this scenario, were to click each of the .item quickly in succession, the AJAX request from a preceeding click is likely to still be waiting for a response. Of course, the new content is also not displayed yet; however, after a handful of seconds and all the requests have had a chance to complete, the user is then barraged with tons of new content being displayed all at once.

What I am after is a method to simply stop execution of any previous click bindings if an .icon is clicked so that only the most recent click ultimately completes.

I am aware that I can make my AJAX call syncronous instead, but I am hoping for a better way that will not seize the user's browser. My jQuery is good enough to get by, but this is something a little more in-depth than I'm used to.

Upvotes: 0

Views: 140

Answers (2)

fortegente
fortegente

Reputation: 1391

First you have to unbind click:

<script type="text/javascript">
    jQuery('.icon').click(function(){
        $('.icon').unbind('click');  // unbind click
        runAjaxStuff();
        displayNewContent();
    })
</script>

Then bind it again in complete event that has $.ajax method:

complete: function() {
    $('.icon').bind('click'); // will fire either on success or error
}

Upvotes: 0

epascarello
epascarello

Reputation: 207501

You got two choices

You can cancel the previous Ajax calls that are open

var xhr = null;
jQuery('.icon').click(function () {
    if (xhr &&  && xhr.readystate != 4) {
        xhr.abort();
    }
    runAjaxStuff();
    displayNewContent();
});

and in your ajax call you would store the call to the

xhr = $.ajax({
    url: 'ajax/progress.ftl',
    success: function(data) {
        //do something
    }
});

or

You can set a "active" flag and not make calls until the last one is complete

var isActive = false;
jQuery('.icon').click(function () {
    if (isActive) {
        return;
    }
    isActive = true;
    runAjaxStuff();
    displayNewContent();
});

and in the success/error/done function

isActive = false;

And you probably want to give the user some notification that either the call is active or that the last call was cancelled just so they know what is happening. Give them a good UX so they do not randomly click.

Upvotes: 3

Related Questions