0

Please, help me create right event for my situation. I believe there is true way to do it, without any counters (like this: How to know when all ajax calls are complete)

HTML:

<ul id="links">
    <li><a href="1.html">What is Yoda's first name?</a></li>
    <li><a href="2.html">Why does Padme die?</a></li>
    <li><a href="3.html">Who is Darth Rage?</a></li>
</ul>
<div id="content"></div>

jQuery:

$('#links a').each(function (index, el) {
    url = $(el).attr('href');
    $('<div class="article" />').appendTo('#content')
        .load(url, function(){
            filterOneArticle(this);
        });
});

// I want this function run after all articles will be loaded and filtered 
$.bind('yepAllArticlesHaveBeenLoaded', filterAllArticles);

filterAllArticles = function() {};
filterOneArticle = function(el) {};
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

3 Answers3

1

There an ajaxStop global event for this:

$(document).ajaxStop(filterAllArticles);

To unbind it so it doesn't run when the next ajax batch finishes (if there is any more ajax activity later), you can just call .unbind() in your filterAllArticles method:

$(document).unbind("ajaxStop", filterAllArticles);
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • Oh, thanks, it works great when there are only those ajax requests. But imagine that there are other requests, for example image galleries etc. `ajaxStop` will be fired only after **all** requests will be completed, but i need filter articles just after articles will be loaded. –  Nov 29 '10 at 13:47
  • @pereskokov -if you need it for just the articles and there are requests *at the same time*, then use a counter, you have no choice there. – Nick Craver Nov 29 '10 at 13:50
  • Thanks a lot, now I am sure that there are no ways except counters. –  Nov 29 '10 at 14:00
1

If for whatever reason you don't want to use ajaxStop as Nick suggests (perhaps you're worried about other, unrelated ajax requests throwing you off), you can keep track of how many requests you've issued and check when each one succeeds/fails:

var requestCount = 0;
$('#links a').each(function (index, el) {
    url = $(el).attr('href');
    ++requestCount;
    $('<div class="article" />').appendTo('#content')
        .load(url, function(){
            filterOneArticle(this);
            --requestCount;
            if (requestCount == 0) {
                filterAllArticles();
            }
        });
});

That looks like it has a race condition (What if the first article finishes loading before we've requested the second?), but it doesn't. JavaScript on browsers is single-threaded (barring the use of web workers, which you have to do explicitly), and so we know we'll finish our loop initiating the requests before the first completion can come through.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks a lot, now I am sure that there are no ways except counters. –  Nov 29 '10 at 14:00
1

jQuery supports this behavior. you can use jQuery to do the ajax call as show below. this method has two call back functions for success and for failure.

function loadData()
{
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        url: 'methodurl',
        success: methodSuccedded,
        error: methodFailure
    });
}

function methodSuccedded()
{}

function methodFailure()
{}
Ghyath Serhal
  • 7,466
  • 6
  • 44
  • 60