Friday, September 14, 2012

JavaScript - Promises, Promises

Now that the web development field is shifting more and more to the client, asynchronous calls in JavaScript are becoming more and more frequent. Many times recently, I've seen scenarios where there are callbacks of callbacks of callbacks in order to load multiple items, which are often independent of one another, prior to some other code executing. I like to call this code "The Flying V".

FLYING V!!!

$.ajax(options)
   .success(function(x) {
      $.get(url, function(y) {
         $.post(url, data, function(z){ 
            doSomethingHere();
         });
      });
   });

What's going on in this scenario is pretty common: There is a bunch of data needing to be loaded, and/or other asynchronous tasks, and the author isn't quite sure what to do to have something fire only when it's all done.

Promises to the rescue. Believe it or not, most popular JavaScript libraries already implement a Promise pattern: JQuery does and so does AngularJS. So if you're using one of these you're in luck, all you need to do is leverage a little known feature of your favorite library.

Here is an example of Promises in JQuery:

$.when(
  $.ajax(options),
  $.get(url),
  $.post(url, data)
).then(function() {
  doSomethingHere();
});

But what if you don't have access to this? What if you're using the best library ever: Vanilla JS? Well, then you can roll your own, or use this simple promise code I put together. I put it up on GitHub, so use it, fork it, blame it, whatever. It's a pretty small amount of code ~480 bytes minified.

Simple promise


Here's a sample of it being used:




This is an extremely simplistic implementation. There are more robust and mature implementations out there. Kris Kowal's Q is a great example of this. It's my understanding that his work is what AngularJS based their promise system off of. I'm sure Mr. Kowal would probably find my simple implementation laughable, but it's made to be lightweight and do one thing.

13 comments:

  1. What about error handling if the ajax function fails? Will the other functions still execute?

    ReplyDelete
  2. By other functions, I assume you mean the other async/ajax calls? Yes, They will all execute immediately, and they're asynchronous, so they're al going to succeed or fail independent of one another.

    With the "when()" or $.when() You're executing all of the async calls immediately, but there's code to notify you of their success or failure. JQuery's implementation also has a completion notification function as well.

    You can also wire up individual success/fail calls on top of the collective when/then call.

    I hope that helps. I felt like I was talking circles when I typed it.

    ReplyDelete
  3. This may be a naieve question, but it is not intended to be. I'm just trying to learn how I could use promises. Does the implementation of promises in JavaScript require one to use setTimeout or other timer functions, or can it be done without that? Many examples I have seen of promsies have used these functions.

    ReplyDelete
  4. It's an understandable question.

    Promises are used to fire an event when one or many asynchronous calls complete. The setTimeout function is used to create an asynchronous call in JavaScript. I have a blog entry about that here: http://www.benlesh.com/2012/05/calling-javascript-function.html

    The reason you see this with Promise implementation demo code is because it's the quickest and easiest way to create an asynchronous call.

    So I guess to answer your question: No, you don't have to use setTimeout() for a promise implementation.

    ReplyDelete
  5. Nice. Examples I've seen of promises and asynchrony have usually involved the timer functions or the built-in event methods such as onreadystatechange. Addy Osmani has a write up on Douglas Crockford's promises implementation at http://www.benlesh.com/2012/05/calling-javascript-function.html that doesn't involve any of these, but I haven't been able to find an example that uses it. Would his implementation really work and truly be asynchronous? It would be nice to see a working example of his implementation.

    ReplyDelete
    Replies
    1. I guess the link you added to your comment is the wrong one. It looks like it's to something on my blog. I Googled a bit, but the only thing I could find where Addy Osmani was talking about promises looked like he was using them to load JavaScript modules from .js files asynchronously via AJAX. So in that case the source of the asynchronisity would be no different than any other HTTP request (a GET or POST for example).

      Common sources for async calls in JavaScript are: XmlHttpRequest (aka AJAX, or HTTP request), calls to local storage, file i/o, setTimeout and setInterval. If you're in Node.JS, then there are as many sources of async calls as any other language. Really any source of I/O: Networking, reading/writing to disk, user input, database calls, timeouts, etc. etc.

      In the case of writing up something "quick and dirty" to demonstrate an asynchronous call, setTimeout is the way to go in most cases.

      Delete
    2. Sorry, the correct link is http://addyosmani.com/blog/lessons-from-a-javascript-code-review/.

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I'm curious to find out what blog platform you are working with?

    I'm having some minor security issues with my latest website and I would like to find something more secure.
    Do you have any recommendations?

    Feel free to visit my weblog

    ReplyDelete
  8. Pretty nice post. I simply stumbled upon your weblog and wished
    to mention that I've really enjoyed surfing around
    your weblog posts. In any case I'll be subscribing for your feed and I am hoping you
    write again very soon!

    Also visit my web blog

    ReplyDelete
  9. This comment has been removed by a blog administrator.

    ReplyDelete

This form allows some basic HTML. It will only create links if you wrap the URL in an anchor tag (Sorry, it's the Blogger default)