Reputation: 1253
I want to wait for multiple promises to be resolved. The method of choice is using jQuery's $.when()
function to wait for all of them:
let test = $.Deferred();
$.getJSON('test.json')
.done((content) => {
test.resolve(content);
});
$.when(
test,
$.when(17)
).done((testContent, value) => {
console.log('test content: ' + testContent.first);
console.log('value: ' + value);
});
The used test JSON file (test.json
) looks like this:
{
"first": "one",
"second": "two"
}
The expected and actual output on the console is:
test content: one
value: 17
But: (Lo And Behold!)
$.when(
$.getJSON('test.json'),
$.when(17)
).done((testContent, value) => {
console.log('test content: ' + testContent.first);
console.log('value: ' + value);
});
With this code, the output changes to:
test content: undefined
value: 17
WHAT? undefined? Please note that the only difference in code is that the $.getJSON
function is used directly as one of the deferreds in the $.when
instruction instead of being extracted to a separate deferred.
Why? What's the difference?
It seems to me like jqXHR style deferreds are not 100 % compatible to jQuery's $.when
function.
$.when
Why does this work, but I cannot use the $.getJSON
jqXHR object directly in the $.when
function?
I am using jQuery 3.2.1.
Update 29.04.2017
I created a fiddle.
As you can see, if I embedd the jqXHR promise directly in the $.when
instruction, the result of this promise is not only the JSON value, but an array of:
[ JSONValue, statusCode, XHR ]
Why does jqXHR behave differently in $.when
then when used outside of $.when
?
Upvotes: 1
Views: 41
Reputation: 780842
You're getting an array of values because jqXHR
resolves to multiple values (the 3 arguments that are normally passed to the .done()
method). From the $.when
documentation:
If a Deferred resolved to a single value, the corresponding argument will hold that value. In the case where a Deferred resolved to multiple values, the corresponding argument will be an array of those values.
So you need to index or destructure the result to get the value you want.
$.when(
$.getJSON('test.json'),
$.when(17)
).done(([testContent, textStatus, jqXHR], value) => {
console.log('test content: ' + testContent.first);
console.log('value: ' + value);
});
You're not seeing this when you use the separate promise, because you're just resolving it with a single value in
(content) => {
test.resolve(content);
}
You would see the same array behavior if you passed all the parameters when resolving the promise:
let test = $.Deferred();
$.getJSON('https://api.myjson.com/bins/bmguh')
.done((content, status, jqXHR) => {
test.resolve(content, status, jqXHR);
});
$.when(
test,
$.when(17)
).done((testContent, value) => {
console.log('Separate promise:', JSON.stringify(testContent));
});
// jqXHR used directly in $.when:
$.when(
$.getJSON('https://api.myjson.com/bins/bmguh'),
$.when(17)
).done((testContent, value) => {
console.log('jqXHR used directly:', JSON.stringify(testContent));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 1