karacsi_maci karacsi_maci - 1 month ago 11
jQuery Question

$.when with dynamic input params and arguments

I have a pool, where I store data, and iterate through on the items by cycles.

Limit is 3, so I get first trhee items, second three items, and the remaining items.

ajax.php
is waiting seconds what comes from pool array. So the first cycle
1,2,4
should be released after
4
seconds, second is
2,1,4
also
4
seconds, and the remaining
3,1
is
3
seconds.

The problem is that
$.when
is get the ajax calls immediatly, even it they have do not has
responseText
. I'vd tried to add the
.apply
but in that case my browser is freezing...

It logs all the requests as object, but without responseText. When the 4 sec is loged, after 4 seconds the responseText is attached to it.

How can I solve this?

var queue = {
limit: 3,
pool: [
1, 2, 4,
2, 1, 4,
3, 1
]
};


function startAjaxRequests() {
var requests = [];
while (queue.pool.length > 0) {
for (var i = 0; i < queue.limit; i++) {
if (typeof queue.pool[i] !== 'undefined') {
requests.push($.get('/ajax.php', {secs: queue.pool[i]}, function () {}));
}
}
$.when($, requests).done(function () {
//$.when.apply(null, requests).done(function () {
$.each(arguments, function (key, value) {
console.log(value);
});
queue.pool.splice(0, queue.limit);
requests = [];
});
}
console.log('finish...');
}

startAjaxRequests();


If I am using like this:

var a1 = $.get('/ajax.php', {secs: 1});
var a2 = $.get('/ajax.php', {secs: 2});
var a3 = $.get('/ajax.php', {secs: 4});
$.when(a1, a2, a3).done(function () {
$.each(arguments, function (key, value) {
console.log(value);
});
});


then it works as it should, and console the results after 4 seconds.

Answer

I'vd tried to add the .apply

That would be correct.

but in that case my browser is freezing...

This is because of your while loop. Ajax (and $.when) is calling your callbacks asynchronously, so you already enter the next iteration before your pool ever empties - and that's effectively an infinite loop. Working with asynchronous code, you need to use a recursive approach instead of a synchronous loop.

function startAjaxRequests() {
    if (queue.pool.length > 0) {
        var requests = [];
        for (var i = 0; i < queue.limit; i++) {
            if (typeof queue.pool[i] !== 'undefined') {
                requests.push($.get('/ajax.php', {secs: queue.pool[i]}));
            }
        }
        $.when.apply($, requests).then(function () {
            $.each(arguments, function (key, value) {
                console.log(value);
            });
            queue.pool.splice(0, queue.limit);
            startAjaxRequests(); // recurse!
        });
    } else {
        console.log('finish...');
    }
}