0
$(".item").each(function(){
    var item_link = $(this).find("a").attr("href");
    $(this).prepend('<div class="img_url"></div>');
    var img_url = $('div.img_url', this);
    $.get(item_link, function(data) {
        var src = $('.poster img', data).attr('src');
        img_url.html(src);
    });
});

Each .get should be started after the previous is finished. Now all the .get start in one time.

Any idea?

gnarf
  • 105,192
  • 25
  • 127
  • 161
Happy
  • 881
  • 7
  • 16
  • 32
  • javascript is not multi-threaded - what makes you think they are started at the same time? – Chadwick Jun 16 '10 at 19:31
  • Therea are ~50 .item blocks on the page, I get "503 Service Temporarily Unavailable" when I start this script – Happy Jun 16 '10 at 19:39
  • this works, but doesn't show all src values, becouse sometimes .get gives 503 error - limit on one time connections – Happy Jun 16 '10 at 19:40
  • 1
    See Also: [Sequencing ajax requests](http://stackoverflow.com/questions/3034874/sequencing-ajax-requests) – gnarf Jun 16 '10 at 20:12
  • There is a native solution on jQuery 1.5+, no need of plugins, try using $.when(): http://api.jquery.com/jQuery.when/ – Chepech Sep 12 '12 at 20:23

4 Answers4

4

NOTE: The plugin quoted here was updated for jQuery 1.5+, follow the link to the original question to get the newest version.


You could use this $.ajaxQueue() originally posted on my answer to Sequencing Ajax Requests

(function($) {
  // jQuery on an empty object, we are going to use this as our Queue
  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {
    // hold the original complete function
    var oldComplete = ajaxOpts.complete;

    // queue our ajax request
    ajaxQueue.queue(function(next) {

      // create a complete callback to fire the next event in the queue
      ajaxOpts.complete = function() {
        // fire the original complete if it was there
        if (oldComplete) oldComplete.apply(this, arguments);

        next(); // run the next query in the queue
      };

      // run the query
      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

Applied to your source

$(".item").each(function(){
    var item_link = $(this).find("a").attr("href");
    $(this).prepend('<div class="img_url"></div>');
    var img_url = $('div.img_url', this);
    $.ajaxQueue({
     url: item_link, 
     type: 'GET',
     success: function(data) {
        var src = $('.poster img', data).attr('src');
        img_url.html(src);
     }
    });
});
Community
  • 1
  • 1
gnarf
  • 105,192
  • 25
  • 127
  • 161
2

jQuery is not threaded by default, but I've written plugins that provide functionality that emulates it. There are two parts to the code. The first creates 'Work Queues' and provides functionality for both a foreground and a background Queue where foreground work is prioritized over background work. It's available in this post: http://code.ghostdev.com/posts/javascript-threading-revisted-jquery. The second creates an AJAX Queue which takes priority over the foreground and background Queues and suspends operation while an AJAX call is processing. It's available in this post: http://code.ghostdev.com/posts/javascript-threading-ajax-queueing.

Using them will absolutely require at least some restructuring of your code, but I've implemented them so that I can avoid browser timeouts and schedule things.

Sorry, I can try to include a bit of an example. Assuming you've included those snippets and now have working queues, something like this probably comes close with your example code:

$.addajaxwork('imageLoading', $('.item'), function () {
  var item_link = $(this).find("a").attr("href");

  $(this).prepend('<div class="img_url"></div>');

  var img_url = $('div.img_url', this);

  $.get(item_link, function(data) {
    var src = $('.poster img', data).attr('src');
    img_url.html(src);
  });
});
g.d.d.c
  • 46,865
  • 9
  • 101
  • 111
1

You could use jQuery's queueing mechanism:

var queueable = $(".item");

queueable.each(function(){

    var item_link = $(this).find("a").attr("href");
    $(this).prepend('<div class="img_url"></div>');
    var img_url = $('div.img_url', this);

    $.queue(queueable, 'get', function(next){
        $.get(item_link, function(data) {
            var src = $('.poster img', data).attr('src');
            img_url.html(src);
            next();
        });
    });

});

$.dequeue(queueable, 'get');
James
  • 109,676
  • 31
  • 162
  • 175
  • creates only for the first .item – Happy Jun 16 '10 at 20:01
  • Assuming there is more than one `.item` matched in `queueable`, this is creating a multiple 'animation' queues (on each item in `queueable`) which contain multiple ajax requests (one for each item in `queueable`) – gnarf Jun 16 '10 at 20:11
  • @gnarf, Nope. `queueable` is what the queue is being tied to (as in the jQuery instance itself) -- not the elements within. Check the source for `jQuery.queue`. And they're not "animation" queues. – James Jun 16 '10 at 22:01
0

You need to use $.ajax() and set async to false.

In this case, you would write:

$.ajax({
    url: itemlink,
    async: false,
    success: function(data) {
       //your success function
    });

or something like that.

Skilldrick
  • 69,215
  • 34
  • 177
  • 229
  • 1
    Easy solution, but will hang the browser during execution. Look into `queue` s for an asynchronous solution that is also sequenced. – MvanGeest Jun 16 '10 at 19:42
  • can you describe, how to use it? Tryed to replace .get with .ajax - doesn't work – Happy Jun 16 '10 at 19:47
  • -1: Synchronous calls may "work" but they are **not** a good solution to solve the problem. Event blocking, poor practice. – gnarf Jun 16 '10 at 20:23