

Multiple Simultaneous Ajax Requests (with one callback) in jQuery - uptown
http://css-tricks.com/multiple-simultaneous-ajax-requests-one-callback-jquery/

======
Cthulhu_
globalStore? Ewwwww. As the jQuery documentation states on $.when [1], the
.then() callback function will be called with a number of arguments equal to
those passed to $.when(), ergo in this example:

.then(function(html, css, feature) {});

Which avoids the need for a global / shared object. If you need access to
these resources outside of this one callback, prefer to pass the promise
object itself around; promises allow multiple 'then's to be added, either
before or after the promise resolves.

I'm working on a blog post about promises and related patterns (in the context
/ implementation of Angular, but they're equally valid for jQuery or other
promise implementations), I'll post it on HN hopefully somewhere this weekend
or early next week.

[1] [https://api.jquery.com/jQuery.when/](https://api.jquery.com/jQuery.when/)

~~~
chrisabrams
Thank you for clarifying this!

------
zimbatm
This is the proper solution: [http://css-tricks.com/multiple-simultaneous-
ajax-requests-on...](http://css-tricks.com/multiple-simultaneous-ajax-
requests-one-callback-jquery/#comment-1154646)

~~~
taf2

       $.when(
         // Get the css-tricks once
         $.get("http://css-tricks.com"),
    
         // get it twice
         $.get("http://css-tricks.com")
        ).then(function( csstricks1, csstricks2 ) {
          
          console.log( 'Fetched css tricks' );
      
          console.log( csstricks1, csstricks2 );
        });
    

csstricks1[0] is the content object and usually what you'll want - for
example, if the response is json.

~~~
sopooneo
Why would you fetch the same thing twice? Or is that just for you example and
wouldn't be done in reality?

~~~
zachrose
Just to be sure that one of them isn't corrupted.

------
ntoll
Can't get enough of deferreds and promises? Want lots more examples of
interesting, cunning and mind bending ways to use promises and deferreds? As
luck would have it, this:

[http://shop.oreilly.com/product/0636920030508.do](http://shop.oreilly.com/product/0636920030508.do)

...has just been published.

(N.B. I'm one of the authors - all feedback would be most welcome and
apologies for the shameless plug).

~~~
fourstar
I don't mean to shit on your book, but an entire book dedicated to jQuery
deferreds? There is that much to say about them?

~~~
terrycojones
It's more a matter of learning how you can use them in various ways, and also
of really getting into the habit of thinking with deferreds. I've been using
them for about 7 years (mainly in Python) and I'm still finding interesting
new ways to think about them, new tricks, etc. [Disclaimer: I'm also one of
the book's authors.] BTW, if you use AUTHD as a discount code on the O'Reilly
site, you'll get 50% off the e-book price or 40% off a dead tree version.

------
Garmonidas
Nice introduction to the promise concept. It's very interesting take a look to
the oficial documentation [https://api.jquery.com/category/deferred-
object/](https://api.jquery.com/category/deferred-object/) for more advanced
features.

------
domrdy
And remember to use fun.prototype.apply if you're argument to $.fn.when is an
array of deferreds or a function call that returns said array. E.g.
$.when.apply(thisArg, array_of_deferreds).

------
baddox
Please let me know if this is a horrible UI pattern (and I'd love to hear
alternatives), but this could also be used to implement something like "do X,
after Y succeeds _and_ at least Z milliseconds have passed".

For example, if you have a Search button that makes an AJAX request, and
there's a loading spinner while waiting for that request, you could use this
technique to make the spinner show for at least, say 500 milliseconds. I have
noticed that a lot of AJAX search forms return so quickly that the loading
spinner just barely flickers before the results display. It might be less
jarring if you ensured that the spinner would show for at least 500 ms. Of
course, you don't just want to _add_ a 500 ms delay after the request returns,
because then slow requests will get that much slower.

------
Groxx
Or you can make a count-down latch of some kind:

    
    
      var num_results = 3;
      var results = []
      var makeCallback = function(index) {
        return function(response) {
          num_results -= 1;
          results[index] = response;
          if (num_results > 0) {
            return;
          }
          
          // actually do stuff here, all results are loaded.
        };
      };
      $.get("/a", makeCallback(0));
      $.get("/b", makeCallback(1));
      $.get("/c", makeCallback(2));
      // etc
    

It's also not hard to make a generic latch-producing function so you can just
write stuff like:

    
    
      var l = makeLatch(callback);
      $.get("/a", l());
      $.get("/b", l());
      $.get("/c", l());

~~~
Stal3r
Yes, you can reinvent wheels and avoid javascript best practices, and lose all
benefits of async code control.

~~~
Groxx
Latches aren't async code control? Javascript has (async) best practices that
survive more than a couple years?

Promises are great, I totally agree (as long as they're A+ compliant). But
they're not on every platform, and it's not (usually) worth building your own
if it's not there.

------
wildpeaks
Like many, I had written myself a similar utility some years ago because "I
need several stuffs that don't depend on each other, so they could be
downloaded or calculated at the same time to get the end result faster" is a
pattern that often comes up.

Nowadays I use "async.js"
([https://github.com/caolan/async](https://github.com/caolan/async)): does the
same, but with extra features.

It doesn't rely on jQuery unlike the snipplets of the article, so it's useful
when you're aiming for vanilla or want to share code with Node.

It's far from the only library of this type, but I like it because it's
reliable and has a good balance of simple yet tweakable for uncommon
workflows.

~~~
wildpeaks
I also like promises-style solutions, but in practice it felt like it needed
more things modified to work with them than async when mixing with third-party
libraries required by projects, but that's more a gut feeling than backed by
hard numbers, so I'll reevaluate that assertion when the right project comes
along.

------
gumballhead
As as extension to this idea, I do stuff like this sometimes in coffee.

$.when.apply($, (object.request() for object in objects)).done (responses...)
-> doStuff()

------
vittore
Why he says about one callback when he really has four? Not even saying about
globalStore.

------
nej
This is pretty similar to using RequireJS no?

------
hipsters_unite
Promises are the way you should be doing AJAX, really.

~~~
vittore
And that is how $.when and $.then works, no?

~~~
hipsters_unite
...which is why I upvoted the post? Just saying, a lot of people aren't aware
jQ even has them, even if it's not inline with the A+ spec.

------
EGreg
Yes, promises are great. It would be nice to have a function on a promise that
returns a regular callback which you can pass to functions that only know
about callbacks.

Also, if you are using promises for getter functions, you'll have to store
those promises somewhere, so that next time you don't load them again.
Basically "getting" a resource involves caching, promises, and maybe even
throttling. So its ideal implementation is not really just a promise.

Check this out:
[http://platform.qbix.com/guide/patterns](http://platform.qbix.com/guide/patterns)

