Reputation: 2089
I have a function that basically looks like this:
function defTest()
{
var dfd = new jQuery.Deferred();
$.ajax(
{
type: "GET",
url: 'http://XXXX',
cache: false,
dataType: "json",
success: function(data,status)
{
console.log('ajax done: success');
dfd.resolve();
},
error: function(data,status)
{
console.log('ajax done: fail');
dfd.reject();
}
});
console.log('about to return dfd');
return dfd;
}
I call it like this:
defTest().then(.....);
The console log produce this: about to return dfd code.js:106 ajax done: success code.js:96
What confuses me is that the code seems to work. Still the dfd is returned BEFORE the ajax has finished. So i removed the return dfd. And put it last in each ajax handler function to make sure that this will NOT be returned until the Ajax has finished.:
success: function(data,status)
{
console.log('ajax done: success');
dfd.resolve();
return dfd;
}
Then it didn´t work at all. I am confused! Can someone explain to me why my deferred can´t be in the ajax success and error handlers and why it works even though it seems that my deferred object returns even if it is fired BEFORE the Ajax is finished and then be resolved or rejected? How is that even possible?
EDIT: This issue is directly linked to my previous unanswered and more complex function: Problems with deferred object
This is why i can´t just "return ajax(...)" because my real function contains other ajax calls that will be apart of ONE result handed back to the caller.
Upvotes: 0
Views: 4393
Reputation: 1153
Of course it's returned right away, that's the point. One would be returning the promise member of the deferred object, normally, though -- although you could return the deferred object and use returnedDeferredObject.promise().then() in code that calls this function.
If you have processing that's dependent on the AJAX completion, that processing goes in the .then() function of the returned .promise(). The beauty is in that while the asynchronous processing is going on, you can do other things that aren't dependent on the AJAX return. You can pass that returned .promise() around to other code.
var mydata = somethingThatReturnsPromise(args);
// do a whole bunch of things
mydata.then(function (returnedReponse) {
// do stuff with returnedResponse that doesn't require DOM ready
});
$(function () {
mydata.then(function (returnedResponse) {
// do DOM stuff with returnedPromise
});
});
I hope I'm not missing your point, but I like to think of that returned promise as a data source that I can use again and again later on, and the .then() callbacks I specify will only be executed once there's a returnedResponse.
As a side note, I am pretty sure that with jQuery going more towards the promise standard, .done(), .pipe(), .fail() and .progress() should be replaced with use of .then(successCb, failCb, progressCb).
Upvotes: 1
Reputation: 1
I believe that your problem is that you are returning the entire deferred object, rather than that object's promise.
The promise, afiak, is always returned before the asynch call is returned, so while your last console.log will trigger before the PROMISE is returned, it will happen well before the ajax is resolved.
using .then() is also probably not what you want, since it fires no matter what the status of the deferred object is: http://api.jquery.com/deferred.then/
You probably want .done()
Try this:
function defTest()
{
var dfd = $.Deferred();
$.getJSON("http://XXXX").done(function(data,success){
console.log('ajax done: success');
dfd.resolve(data);
}).fail( function(data,status) {
console.log('ajax done: fail');
dfd.reject();
});
console.log('about to return dfds promise');
return dfd.promise;
}
defTest().done(function(data){ console.log(data); });
Upvotes: 0
Reputation: 12705
there are many questions like this
the AJAX
request is async
in nature so in the first example when you were returning it in the last line.
it dosent wait for the async ajax
to complete
and in the second case the function is already over and putting return in success would obviously not return anything as you are not calling the method assigned to success
event directly
UPDATE:- after the comment
because after returning the deffered
object you are doing defTest().then(.....);
so the function inside the then handler will obviously be fired when the deffered
object is resolved.
probably you should check the value of the deffered
object as soon as you return it and not using .then()
and you will get what mistake you are making here
Update 2 -
have a look here http://jsfiddle.net/BtEKa/ im getting predictable results
Upvotes: 1
Reputation: 9822
Your call to defTest
will return as soon as your ajax call is started.
It will not wait until deferred is resolved or not.
But you are perfectly able to do what you want:
defTest().then(function() { console.log("deferred done"); })
It will print deferred done
when deferred is finally resolved.
By the way, as suggested by xdazz, $.ajax
returns already a Deferred.
Upvotes: 1
Reputation: 160853
$.ajax
returns a Deferred object, so you only need to return it.
return $.ajax(...
Upvotes: 1