I have the following code:
$.when(loadProjects())
.then(function() {
$.when.apply($, buildRequests(projects))
.then(function(data) {
$.when.apply($, vcsRequests(buildTypes))
.then(function(data) {
$.when.apply($, vcsDetailRequests(vcsRoots))
.then(function(data) {
alert('done');
});
});
});
});
Each of the functions passed into when.apply() return arrays of requests. I cannot perform the buildRequests calls until the calls from loadProjects() has finished as they rely on information returned from those calls. Each call depends on information returned by the previous call, so they must be in this order. I need to know when all the calls have finished so I can process the data returned.
Is there a cleaner way to approach this?
I have the following code:
$.when(loadProjects())
.then(function() {
$.when.apply($, buildRequests(projects))
.then(function(data) {
$.when.apply($, vcsRequests(buildTypes))
.then(function(data) {
$.when.apply($, vcsDetailRequests(vcsRoots))
.then(function(data) {
alert('done');
});
});
});
});
Each of the functions passed into when.apply() return arrays of requests. I cannot perform the buildRequests calls until the calls from loadProjects() has finished as they rely on information returned from those calls. Each call depends on information returned by the previous call, so they must be in this order. I need to know when all the calls have finished so I can process the data returned.
Is there a cleaner way to approach this?
Share Improve this question edited Feb 10, 2012 at 11:30 JFoulkes asked Feb 10, 2012 at 9:56 JFoulkesJFoulkes 2,4191 gold badge21 silver badges26 bronze badges 4- Seems you have lot of requests to chain. I would then consider bining all request into single one.... much more efficient than chaining... – Jovan Perovic Commented Feb 10, 2012 at 10:12
- How would I go about doing that? I have to call one after another because of the API I'm using. – JFoulkes Commented Feb 10, 2012 at 10:16
- I posted the answer on how to achieve this because ments don't really like code formatting :) – Jovan Perovic Commented Feb 10, 2012 at 10:27
- I thought the example in this answer was incredibly useful in understanding the concept of pipes: jquery-ajax multiple calls – blong Commented Jan 24, 2013 at 22:10
3 Answers
Reset to default 2I came across yepnope.js the other day. I haven't tried it myself yet, but it might be helpful if you're doing a lot of ajax loading.
Actually thinking this over makes me realize that yepnope.js is not really applicable to your case. What I would consider in your case is to have loadProjects()
et al return a single promise by applying when()
internally in each function. Also putting pipe()
to use could lead to something like
loadProjects().pipe(buildRequests).pipe(vcsRequests).pipe(vcsDetailRequests);
Sample buildRequests()
:
function buildRequests(projects){
// Do something using projects
// ...
var requestsPromise = ...; // Finally get ajax promise for requests
return requestPromise;
}
The result of the requestPromise
will then be passed into the next piped function once it is resolved/rejected.
From the docs on pipe()
:
// Example: Chain tasks:
var request = $.ajax( url, { dataType: "json" } ),
chained = request.pipe(function( data ) {
return $.ajax( url2, { data: { user: data.userId } } );
});
chained.done(function( data ) {
// data retrieved from url2 as provided by the first request
});
Dependence chain of AJAX requests : You can chain multiple AJAX request — for example, first call retrieves the user details of a user, and we need to pass that value to second script. Remember that $.then()
returns a new promise, which can be subsequently passed to the $.done()
or even another $.then()
method.
var a1 = $.ajax({
url: '/first/request/url',
dataType: 'json'
}),
a2 = a1.then(function(data) {
// .then() returns a new promise
return $.ajax({
url: '/second/request/url',
dataType: 'json',
data: data.userId
});
});
a2.done(function(data) {
console.log(data);
});
.... response according to my ment on original post:
Seems you have lot of requests to chain. I would then consider bining all request into single one.... much more efficient than chaining...
Well, something like this:
PHP:
$projects = YourAPI::loadProjects();
$builds = YourAPI::getBuilds($projects);
$vcs = YourAPI::getVCS($builds);
$details = YourAPI::getVCSDetails($vcs);
// for example
return json_encode($details);
// OR, if you need all the data
$results = array(
"projects" => $projects,
"builds" => $builds,
"vsc" => $vcs,
"details" => $details
);
return json_encode($results);
This way, you have inherent synhronization between calls AND less HTTP trafiic ;)