Reputation:
Ok, so I've read 1,000,000+ articles on jQuery deferreds and/or promises, and I'm still getting something wrong.
functionOne() {
var deferred = $.Deferred();
var request = $.ajax({
url: 'http://example.com/mypath/etc'
});
request.done(function(data) {
// TODO: I've got stuff here that takes a while.
deferred.resolve();
});
return deferred.promise();
}
functionTwo() {
// Something that depends on the others being finished.
}
$.when(
functionOne(),
anotherLongRunningFunctionWithAjax())
.then(
functionTwo()
);
I need any function(s) in the "when" to fully complete (.ajax done) before the "then" starts. However, the promise returns immediately (as expected), but functionTwo starts, even though functionOne has not called "done".
I'm sure it's a fundamental misunderstanding of deferred and the chain-of-calls.
Edit:
function functionOne() {
console.log('functionOne called');
var request = $.ajax({
url: 'http://example.com/mypath/etc'
});
request.done(function(data) {
console.log('Starting Done.');
setTimeout(function () {
console.log('Done finished.');
}, 5000);
});
console.log('Returning promise.');
return request;
}
function functionTwo() {
console.log('functionTwo called');
}
$.when(functionOne()).then(functionTwo());
Gives me this in the console:
functionOne called
Returning promise.
functionTwo called (should be called after Done is finished.)
Starting Done.
Done finished.
Upvotes: 2
Views: 1887
Reputation: 351338
Taking the code in your edit, there are two issues:
The timer in functionOne starts after request is resolved, yet you return request. So whatever happens with the timer... it is of not relevance to the returned promise, which at that time is already resolved.
You call functionTwo immediately, instead of passing the function reference for the $.when promise to call back
Here is working code:
function functionOne() {
console.log('functionOne called');
console.log('Returning promise.');
return $.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1'
}).then(function(data) {
console.log('Starting Done.');
var dfd = $.Deferred();
setTimeout(function () {
console.log('Done finished.');
dfd.resolve(data); // indicate when you are done
}, 2000); // 2 seconds will do ;-)
return dfd.promise(); // you need to return a promise again
});
}
function functionTwo() {
console.log('functionTwo called');
}
// don't call functionTwo immediately, leave that to the promise to do:
$.when(functionOne()).then(functionTwo);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 3
Reputation: 171700
you are using an anti-pattern since $.ajax
itself returns a promise
Just do
functionOne() {
var request = $.ajax({
url: 'http://example.com/mypath/etc'
});
request.done(function(data) {
// TODO: I've got stuff here that takes a while.
});
return request
}
Upvotes: 1