Reputation: 12391
I have ajax requests in my requests
array. The number of requests could be 1,2 or 3 (does not matter, dynamically).
The requests like this:
var ajaxRequest = $.get(ajaxUrl, requestData);
I am want to process the results like this:
$.when.apply($, requests).then(function () {
$.each(arguments, function (key, value) {
console.log(value);
//var response = JSON.parse(value[0]); //It is fail if there is only 1 ajax request
});
});
The problem is the arguments
.
If there is only 1 request, than at the each, the values will be
string [the json string, what I want to JSON.parse]
string ['success']
Object [the Ajax request Object]
In this case the arguments length is 3, this will cause problems later.
But, if I have 2 or 3 requests, then I will get back arrays like this, (for example for 2 requests):
Array [json string, 'success', ajax Object],
Array [json string, 'success', ajax Object]
If three requests, of course one more array.
And the problem is here. I can not check the length of arguments, because it is 3 if I have 3 requests, and 3 if I have only one requests.
So I rewrote my script like this:
$.each(arguments, function (key, value) {
if (typeof value === 'string') {
var response = JSON.parse(value);
} else {
var response = JSON.parse(value[0]);
}
$('div[data-id="' + response.productId + '"').find('.dictionaryContainer').find('ul').html(response.html);
});
Now my problem is here:
if (typeof value === 'string') {
even if it is good, the iteration is continuous, maybe it could be hacked somehow with flags, and return ture
s, but I bet, there is some more elegant solution for this.
Can anybody help me to handle this?
Upvotes: 1
Views: 535
Reputation: 43156
Simple work around would be to check the length of requests yourself and adjust what you're iterating on, something like this:
$.when.apply(null, requests).done(function() {
var arg = (requests.length === 1) ? [arguments] : arguments;
$.each(arg, function(i, response) {
console.log(response);
})
});
Something like this fiddle
Upvotes: 2
Reputation: 1074148
Unfortunately, as you've found, the combination of $.when
and the kind of promise is essentially broken because of its chaotic behavior that depends on whether you pass one or two+ arguments to $.when
.
I'd suggest either:
Using promises (with a polyfill if needed) and promise-ifying $.ajax
, $.get
, etc.; then use Promise.all
on the array of promises.
Implementing your own $.whenAll
that isn't chaotic.
Here are rough version of both (just for $.ajax
, you can do your own $.get
and $.post
readily enough):
Rough version of #1: (Note: Creating a new, clean promise rather than reusing $.ajax
's promise in order to just return the result [not success
's other arguments] and return a single object with a rejection [not error
's various discrete arguments].)
$.promiseAjax = function(options) {
return new Promise(function(resolve, reject) {
options = $.extend({}, {
success: function(result) {
resolve(result);
},
error: function(jqXHR, textStatus, errorThrown) {
reject({
jqXHR: jqXHR,
textStatus: textStatus,
errorThrown: errorThrown
});
}
}, options);
$.ajax(options);
});
};
Usage:
var requests = [];
if (someCondition) {
requests.push($.promiseAjax({/*...*/}));
}
if (someotherCondition) {
requests.push($.promiseAjax({/*...*/}));
}
Promise.all(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});
Rough version of #2:
$.whenAll = function(promises) {
var d = $.Deferred();
var results = [];
var counter = promises.length;
promises.forEach(function(promise, index) {
promise
.done(function(result) {
results[index] = result;
if (--counter == 0) {
// All done
d.resolve(results);
}
})
.fail(function() {
d.reject(Array.prototype.slice.call(arguments));
});
});
return d.promise();
};
usge:
var requests = [];
if (someCondition) {
requests.push($.ajax({/*...*/}));
}
if (someotherCondition) {
requests.push($.ajax({/*...*/}));
}
$.whenAll(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});
Upvotes: 1