5

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?

4
  • Seems you have lot of requests to chain. I would then consider combining all request into single one.... much more efficient than chaining... 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. Commented Feb 10, 2012 at 10:16
  • I posted the answer on how to achieve this because comments don't really like code formatting :) 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 Commented Jan 24, 2013 at 22:10

3 Answers 3

2

I 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
});
Sign up to request clarification or add additional context in comments.

4 Comments

Do you have any samples/links on how to do this? I'm new to the whole deffered/promise stuff
Added sample of one of the functions. The others would be similar. See the included link to .pipe() for more about how it works.
I see how pipe will help, the only issue I have now is making this work with a dynamic number of requests which each function returns...
If you don't need to wait for each request individually, then wrap them up in when(), and then in the consumer do function buildRequests(){var projects = arguments; /* then do something with projects, etc. */}. The builtin arguments variable contains all the arguments passed to the function, and when() will be passing the result of each of the project-promises.
2

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);
});

Comments

1

.... response according to my comment on original post:

Seems you have lot of requests to chain. I would then consider combining 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 ;)

3 Comments

I have no intention of using anything apart from javascript
oook, but those ajax requests call some server-side scripts, be it PHP or any other language, is it not?
They are ajax requests to an API which I have no control over

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.