The process of how ideas become working features on the web is a mystery to most people and I suspect that most developers have the sense that they can actually influence that process. Over the past couple weeks a number of articles have appeared discussing the way forward in the open web. They share a core underlying ideal: web developers need the ability to extend the web with new features or in other words:
In order for the open web to compete with its walled competitors, there must be a clear path for good ideas by web developers to become part of the infrastructure of the web. — The Extensible Web Manifesto
In The Extensible Web Manifesto, a number of important figures in the JavaScript community have committed to changing “how web standards committees create and prioritize new features”.
Yehuda Katz fleshes out the ideas of the manifesto in his post Extend the web forward and invites implementers and practitioners to help make it happen. This is a critical piece of the puzzle: to move forward we need not only a clear path for good ideas, we need developers to travel down that path.
Alex Russell is one such developer and he provides a great view into that journey in his post s/Future/Promise/g that describes some of the history and hard work behind the recent developments of the WHATWG DOM spec as it relates to promises which has culminated in not only Mozilla and Google beginning to implement Promises in their engines, but also the W3C TAG recommendation to spec authors “that they adopt Promises for asynchronous, single-valued operations.”
The big reason to spend months of my life on this problem, and to harass other very busy people to do the same, is to me the core value of web standards: when they’re working well, they create a uniform surface area that describes a coherent platform. — Alex Russell
Moving the web forward is hard work but we owe it to each other to participate in the process. Thank you to everyone who tirelessly works towards the future. These are exciting times to be a web developer.
Perhaps you already know this: Express.js and Node.js can be a powerful medium for rapid-prototyping. However, if you’ve never used either one, it may seem daunting to get started. Over the past week, I’ve stumbled across a number of useful articles related to using Express.js — ‘a minimal and flexible Node.js application framework’ that help take any edge off the learning curve. In the hopes that it’s useful, I thought I’d share the list in one place.
Evan Hahn has written an in-depth article — Understanding Express.js — exploring how Express.js actually works. In his words:
It helps you build web apps. If you’ve used Sinatra in the Ruby world, a lot of this will be familiar. It’s good magic… But all magic comes at a price: you might not understand the inner workings of Express.
After you read Understanding Express.js you will have a better idea of what’s happening beneath the abstraction layer.
Next, Eric Elliott has written an article Getting Started With Node.js and Express.js which demonstrates the process of just that. I particularly enjoyed reading through and playing with his code samples.
Finally, there a two-part series was published on A List Apart exploring using Node and Express together to rapidly prototype designs. Taking the idea of Design in the Browser to the next level, the series explores mocking-up data structures and a step-by-step process of creating a mockup you can actually use. In Garann Means words:
implementation tends to expose requirements you hadn’t considered, and some of those can have a considerable impact on your timeline. Even in a server-driven application where it may not be possible to reuse data structures and templates as-is, creating client-only versions helps test your assumptions about the data you need and how you’ll use it.
This book is about front-end web development in this new web-everywhere era. It’s about learning methods to make first-class websites, apps, or anything built on open web technologies, with the multi-device world aforethought. This is not a book about how to make mobile websites or smart TV apps; it’s about learning the latest developments in current and near-future web technologies so you’ll be better able to build sites capable of offering the best experience everywhere. — Peter Gasston
The Modern Web is packed with information. It starts with an introduction to the current landscape of devices and the platform we call the web and ends with a look at what’s still coming down the pipeline. In between you’ll find coverage of the following elements:
The Device Landscape & The Web Platform
HTML5 ( Microdata, WAI-ARIA, data-attributes )
Device Responsive CSS
CSS Layouts ( Flexbox, columns, grid-layout )
JavaScript ( DOM interaction )
Device apis
Images and Graphics ( SVG, canvas )
Forms ( new elements, client-side validation )
Multimedia ( media elements, media fragments, media events, media API )
Future ( web components, custom elements, shadow DOM, regions, exclusions, box-alignment, line grid, paged media, feature queries )
Current State of Browser Compatibility
The explanations are clear, explaining not only the concept and how to use it, but also discussing its potential benefits and pitfalls. At the end of each chapter there are extensive references to each topic covered should you be ready to dive deeper.
It’s important to approach the book knowing what it actually is, and is not about, so as not to be disappointed. This really is a book about understanding and using the evolving technologies we use to build websites and web apps in the changing landscape of the thing we call the web. It is neither an introduction nor a complete reference to HTML5, CSS3 and JavaScript. It discusses developments that you can’t safely use yet along with those you can. It is not a tips and tricks book; instead, it is a deep dive into the big picture, providing introductions to a number of topics which would demand their own book to master.
Of course the question is, how much of what you read about will you actually be able to implement? The answer, of course, depends on the constraints you currently face — or more specifically, the browsers you need to support. While you won’t be able to immediately use and implement everything you find in The Modern Web, that shouldn’t stop you from reading it. The holistic approach takes all the technologies as pieces of a puzzle and helps in framing how they all fit together and why it matters.
If you’re hoping to gain a good overall picture of what the latest developments in front-end technologies are and some ideas on how to use them, The Modern Web is a great place to start. Unless you’re an expert on all of the topics mentioned above, you’re going to pick up some new knowledge.
As a front-end developer, it is important to have an understanding of the context we work in, user trends, technological developments, and the tools that are already at our disposal or will be soon. The Modern Web: Multi-device development with HTML5, CSS3 and JavaScript aims to help fill that gap and it does it well.
My verdict: If you only read one book on the latest developments in HTML5, CSS3, and JavaScript this year, this is the one.
I’m relatively picky when it comes to iPhone apps and iPad apps. I’ve downloaded countless apps and rarely open them more than once before deleting them. Among the apps that don’t get quickly deleted there’s a small group that have made it into my daily or weekly flow for longer than a few days or weeks. These are the apps I ‘love’.
In the spirit of sharing a good thing, I’ve put together a list of the apps that have surprised me and become become an integral part of my regular routine along with what I love about them. Have a look and see if you find a gem worth trying.
TextExpander (iPad / iPhone & OSX)
I was interested in TextExpander for a long time before I finally decided to give it a try. I had a hard time seeing how I would use the mobile app so I started with the free demo for OSX. It only took a few days to realize I loved it and buy the mobile version as well. It’s an app that molds to your needs. I use it for coding on the iPad, correcting spelling, writing markdown, running shell scripts, writing email signatures, creating templates for blog posts, and quickly typing anything I frequently write. I haven’t even begun to scratch the surface. If there’s something you find yourself repetitively typing or doing, TextExpander can make it easier. It will worm its way into your workflow across all devices: once you start using it, you start looking for more ways to use it.
Drafts (iPad / iPhone)
Here’s another app that will slowly worm it’s way into your workflow. What it offers is a simple text window with highly customizable actions for what to do with your text. You can jot something down and return to it later or send it just about anywhere you can imagine: another app, Dropbox, Evernote, your calendar, your to-do list, a browser, append it to a file somewhere, send it as a message, a tweet, a text, or an email. With TextExpander integration and custom URL actions — the sky is the limit. I even have a URL action that quickly generates a Bit.ly shortened link.
1Password (Universal & OSX)
I started using 1Password on my computer hoping for better security ( a different password for every site ) and the convenience of not having to remember it all. I never imagined I would want to use it on an iOS device - after all why use an app with a built in browser when I already have a browser. On the computer I have a hotkey that opens the browser extension and allows me to automatically login to any website I’m on. Once I had all my passwords saved on the computer I found myself wanting the same convenience on my mobile devices. So I broke down and bought it. If I’m going to a site where I need to login, I open the app, put in my master password, choose the site and the app takes me to it and logs me in. It’s also integrated with a number of iOS apps including Drafts which makes it even more useful.
Launch Center Pro (iPhone)
I bought Launch Center Pro because of the promise of actions. One of my favorites: Open the app, pick an action ( search Pinboard ), fill in the prompt and watch as the app magically opens Chrome, and searches my Pinboard links. I use a few actions frequently — they cut down on tapping but honestly I mostly use it to keep my home screen free of clutter and launch my second most used apps from my home screen. It’s like a utility belt for the iPhone and has a spot in my dock.
Textastic (iPad / iPhone & OSX)
Code editing on the iPad? Ridiculous. Or so I thought. I researched every iPad app for coding that’s available - thanks to Brett Terpstra’s brilliant chart. My requirements: TextExpander integration, markdown, web preview, code inspector, Dropbox integration, FTP integration, syntax highlighting, code formatting, the Solarized dark color scheme ( which I also use in Sublime Text and Chrome Developer Tools ), and some form of code completion. Along with all of that Textastic delivers a brilliant navigation and selection system which I have found myself attempting to use in other apps. It’s not easy to write code on a mobile device - but Textastic makes it as easy, pleasant and productive as possible.
Omnifocus (iPad / iPhone & OSX)
I’ve been using Omnifocus on my computer, iPad and iPhone for a number of years now. I’m sure I don’t use all the features available and while my setup and methodology has varied over time as my needs shifted, Omnifocus has always been flexible enough to adapt. I’ve used Omnifocus for everything from a simple to-do list, a way to set reminders, a place to store things I plan to do one day, to an in-depth project management system. The great thing is it can be used for all of those things at the same time.
Writing Kit (Universal) along with terminology (iPad / iPhone)
Writing Kit is truly one of the most brilliant apps I’ve come across. In fact I’m writing this post on it now. Before I discovered Writing Kit I was a devout iA Writer user - loving its pure simplicity. Writing Kit however has mastered the notion of a one window productivity suite with an integrated browser, integrated Terminology, integrated quick web search, quick referencing of other sources, access to saved Instapaper, Readability or Pinboard articles, navigation shortcuts, Markdown shortcuts, live preview and customization options - all from one window. If you write ( and / or research ) on the iPad, you must try Writing Kit. It has expanded my vision of what a task focused app can deliver.
Pocket (iPad / iPhone & OSX)
Up until I discovered Pocket I used Readability and before that I used Instapaper. While I really like the reading experience in these apps, I save a lot of articles with code, videos and presentations which seem less ideally suited for those services. What I love about Pocket is how easy it is to save anything and everything I come across on the web that I’d like to get back to later. Once I’ve read or watched something I can easily tag and archive it or share it to numerous services including Bufferapp and Pinboard. As a result Pocket is my time saving intermediary spot for all interesting things I come across and want to read later, share later or archive later. It also has robust integration with ifttt which makes it all the better.
Day One (iPad / iPhone & OSX)
Day One almost feels like it doesn’t quite fit in this lineup, but I include it because it’s an app I use a lot and it has shifted my online sharing behavior. Day One is pitched as a journal app — making it as easy to record your life as sending a tweet. Day One works for both long-form posts or ‘status updates’. You can add a photo, a location, hashtags, the time and / or the weather along with your text and store it all privately in Dropbox. What I love most about Day One is that there is no audience. Since I started using Day One I’ve found myself sharing more with myself and less on other social media networks. When I think about why I share things on Facebook or Foursquare in particular it’s often to have my own record. With Day One I can share without thinking of my audience, my privacy or how many likes I get.
Conclusion
This post has gotten longer than I planned, so I’ll save discussing games and social media apps for another post. In the meantime, I hope you find a new app that delivers more than you expected!
Disclaimer: All links to apps are affiliate links. When you choose to purchase any app via these links you are supporting this blog which I greatly appreciate. In return I promise to always post truthfully and never intentionally recommend something I don’t believe in.
…explain the concepts of testing and test-driven development, as well as why they’re useful… dive into Jasmine and explain how it can help programmers test their JavaScript code… give readers an understanding of Jasmine’s concepts and syntax. — Evan Hahn
What’s Good
If you’re just getting started with Jasmine and want to save yourself some time researching and reading documentation and blog posts, JavaScript Testing With Jasmine is a concise read that will help take a bit of the pain out of understanding Jasmine.
Misses
I feel like there’s some missed opportunities with the book. It doesn’t seem to offer quite enough information either for a complete beginner or for a seasoned pro.
For a novice in JavaScript or testing, it would have been useful to really dive into the methodology of test-driven development ( TDD ) and behaviour driven development ( BDD ) — ideally walking through the process of building something while teaching the principles.
For the JavaScript developer who’s already familiar with testing in JavaScript it would have been great to dive into the idiosyncrasies of Jasmine along with more practical examples and use cases that touch on complexities, gotchas and best practices.
The verdict
If you already are comfortable using Jasmine, you’re probably not going to find much that’s new here. However, if you have a good understanding of the value of testing JavaScript and are looking to quickly get an overview of Jasmine and save some time getting started, then this short book is worth a look.
Thanks to this article: Client-Side Error Logging With Google Analytics I started an experiment yesterday with logging client-side JavaScript errors as an event in Google Analytics in 3 lines of code. Within a couple hours, I could generate a report of which scripts were causing the most errors, what the errors are, which pages and/or which browsers have the most errors. I still think it would be a good idea to have a dedicated solution, but in the meantime this is a great way to get an instant picture of the current situation.
Here’s the code I’m using in case you want to give it a try.
In part 1 of this post, I spent a lot of time looking at the theory of promises and deferreds: what promises are and how they behave. Now it’s time to actually explore some ways to use promises and deferreds in JavaScript and dive into some best practices. I’ll start with some basic uses and examples of promises and then will dive into a number of specifics pertaining to using promises in jQuery. While the exact specifics of the API may vary from your chosen library, there is enough overlap in concepts to illustrate the use of promises.
Note: The code samples will use jQuery in spite of jQuery’s deviations from the Promise/A proposal, which is particularly noticeable in the case of error handling and when working with other promise libraries. Since part 1 discussed and included links to in-depth articles on the topic, I will refrain from saying anything else about it in this post. The use of jQuery is still wide-spread and their implementation serves as an introduction for many to the use of promises both of which lead me to believe that it is valuable to have an understanding of working with promises in jQuery.
Sequencing Patterns
A deferred is an object representing work that is not yet done and a promise is an object representing a value that is not yet known. In other words, promises / deferreds allow us to represent ‘simple’ tasks and can be easily combined to represent complex tasks and their flows, allowing for fine-grained control over sequencing. This means we can write asynchronous JavaScript parallel to how we write synchronous code. Additionally, promises make it relatively simple to abstract small pieces of functionality shared across multiple asynchronous tasks — consider as an example loading animations, progress animations etc.
Let’s begin with a global view of three common sequencing patterns that promises make possible: stacked, parallel and sequential.
Stacked: bind multiple handlers anywhere in the application to the same promise event.
var request = $.ajax(url);
request.done(function () {
console.log('Request completed');
});
// Somewhere else in the application
request.done(function (retrievedData) {
$('#contentPlaceholder').html(retrievedData);
});
Parallel tasks: ask multiple promises to return a promise which alerts of their mutual completion.
$.when(taskOne, taskTwo).done(function () {
console.log('taskOne and taskTwo are finished');
});
Sequential tasks: execute tasks in sequential order.
var step1, step2, url;
url = 'http://fiddle.jshell.net';
step1 = $.ajax(url);
step2 = step1.then(
function (data) {
var def = new $.Deferred();
setTimeout(function () {
console.log('Request completed');
def.resolve();
},2000);
return def.promise();
},
function (err) {
console.log('Step1 failed: Ajax request');
}
);
step2.done(function () {
console.log('Sequence completed')
setTimeout("console.log('end')",1000);
});
These patterns can be combined or used separately building up complex tasks and workflows.
Common Use Cases
Many examples of promise use cases pertain to Ajax requests and UI animations. In fact jQuery even returns promises by default from Ajax requests. This makes sense given that promises are ideal for asynchronous tasks whose completion needs to be handled in a unique way. However, that doesn’t mean that the use of promises should be limited to these use case. In fact, promises tend to be a tool worth considering anytime you might otherwise reach for a callback. That said, let’s have a look at some ways we can use promises.
Ajax
Examples of using promises with Ajax requests can be found throughout this post, so I will skip an example here.
Timing
We can create a promise based timeout function.
function wait(ms) {
var deferred = $.Deferred();
setTimeout(deferred.resolve, ms);
// We just need to return the promise not the whole deferred.
return deferred.promise();
}
// Use it
wait(1500).then(function () {
// Do something brilliant here!
});
Animation
Obviously the following animation is completely useless, but it serves as an example of how promises and animations can be used together.
var fadeIn = function (el) {
var promise = $(el).animate({
opacity: 1
}, 1500);
// Dynamically create and return an observable promise object which will be resolved when the animation completes.
return promise.promise();
};
var fadeOut = function(el) {
var promise = $(el).animate({
opacity: 0
}, 1500);
// Dynamically create and return an observable promise object
return promise.promise();
};
// With the setup out of the way, we can now do one of the following.
// Parallel
$.when(
fadeOut('div'),
fadeIn('div')
).done(function () {
console.log('Animation finished');
$('p').css('color', 'red');
});
// OR
// Chained
fadeOut('div').then(function (el) {
fadeIn(el); // returns a promise
}).then(function (el) {
fadeOut(el); // returns a promise
});
Synchronizing parallel tasks with $.when()
var promiseOne, promiseTwo, handleSuccess, handleFailure;
// Promises
promiseOne = $.ajax({ url: '../test.html' });
promiseTwo = $.ajax({ url: '../test.html' });
// Success callbacks
// .done() will only run if the promise is successfully resolved
promiseOne.done(function () {
console.log('PromiseOne Done');
});
promiseTwo.done(function () {
console.log('PromiseTwo Done');
});
// $.when() creates a new promise which will be:
// resolved if both promises inside are resolved
// rejected if one of the promises fails
$.when(
promiseOne,
promiseTwo
)
.done(function () {
console.log('promiseOne and promiseTwo are done');
})
.fail(function () {
console.log('One of our promises failed');
});
Decoupling events and application logic
We can also use events to trigger resolution / failure of promises, passing values through at the same time which allows us to decouple application, DOM and event logic ( jsfiddle here ).
var def, getData, updateUI, resolvePromise;
// The Promise and handler
def = new $.Deferred();
updateUI = function (data) {
$('p').html('I got the data!');
$('div').html(data);
};
getData = $.ajax({
url: '/echo/html/',
data: {
html: 'testhtml',
delay: 3
},
type: 'post'
})
.done(function(resp) {
return resp;
})
.fail(function (error) {
throw new Error("Error getting the data");
});
// Event Handler
resolvePromise = function (ev) {
ev.preventDefault();
def.resolve(ev.type, this);
return def.promise();
};
// Bind the Event
$(document).on('click', 'button', resolvePromise);
def.then(function() {
return getData;
})
.then(function(data) {
updateUI(data);
})
.done(function(promiseValue, el) {
console.log('The promise was resolved by: ', promiseValue, ' on ', el);
});
// Console output: The promise was resolved by: click on <button> </button>
Gotcha’s: understanding .then() in jQuery
In order to demonstrate a couple “gotcha’s”, these final examples will walk through part of my learning process when I first started playing with promises.
Let’s assume the following two utility functions for the following examples:
// Utility Functions
function wait(ms) {
var deferred = $.Deferred();
setTimeout(deferred.resolve, ms);
return deferred.promise();
}
function notifyOfProgress(message, promise) {
console.log(message + promise.state());
}
My first attempt at chaining promises together looked something like this:
// Naive attempt at working with .then()
// Create two new deferred objects
var aManualDeferred = new $.Deferred(),
secondManualDeferred = aManualDeferred.then(function () {
console.log('1 started');
wait(3500).done(function () {
console.log('1 ended');
});
});
// After secondManualDeferred is resolved
secondManualDeferred.then(function () {
console.log('2 started');
wait(2500).done(function () {
console.log('2 ended');
});
});
// Resolve the first promise
aManualDeferred.resolve();
Upon executing this, the console output is what I would have expected had I not used promises.
1 started
2 started
2 ended
1 ended
The jQuery API says that .then() is chainable and returns a new promise, so my expectation was that whatever I wrapped in .then() and chained together would occur sequentially and wait for any tasks to finish before moving to the next. Clearly that’s not what happened. Why not?
How does .then() actually work?
Looking in the jQuery source code, we find that:
.then() always returns a new promise
.then() must be passed a function
If .then() is not passed a function:
the new promise will have the same behaviour as the original promise ( which means it is immediately resolved/rejected ),
the input inside .then() will be executed but is ignored by .then()
if .then() is passed a function which returns a promise object:
the new promise will have the same behaviour as the returned promise
You probably already see ( if you didn’t see it right away ) why my version didn’t work.
I didn’t explicitly return a promise from .then() so the new promise created by .then() had the same values as the promise it was chained to.
Avoiding the descent into callback hell
We know we need to pass .then() a function for it to be able to do it’s job and we know we need to return a promise from .then(). So we could do the following:
// Anti-pattern - Return to callback hell
var aManualDeferred = new $.Deferred();
aManualDeferred.then(function () {
console.log('1 started');
return wait(3500).then(function () {
console.log('1 ended');
}).then(function () {
console.log('2 started');
return wait(2500).done(function () {
console.log('2 ended');
});
});
});
// Resolve the first promise
aManualDeferred.resolve();
This works. Unfortunately, it’s starting the decent back into callback hell which is one of the things that promises are supposed to help us avoid. Luckily, there are a number of ways to handle this without decending into the territory of deeply nested functions. How we choose to solve it, is of course dependent on our particular situation.
Avoiding extensive use of unnamed promises
We could for example do the following:
// A chain
// Create new deferred objects
var aManualDeferred = $.Deferred();
aManualDeferred.then(function () {
console.log('1 started');
// We need to return this, we return a new promise which is resolved upon completion.
return wait(3500);
})
.then(function () {
console.log('1 ended');
})
.then(function () {
console.log('2 started');
return wait(2500);
})
.then(function () {
console.log('2 ended');
});
// Resolve the first promise
aManualDeferred.resolve();
This version admittedly reads very nicely but has the disadvantage of only one named promise which doesn’t really give us the fine-grained control over each step in the process that is desirable in many situations.
Unwinding promises and their handlers
Assuming we want to avoid deeply nested functions and that we should name our promises to give us access to each step of the process, here is a final version:
var aManualDeferred, secondManualDeferred, thirdManualDeferred;
// Create two new deferred objects
aManualDeferred = $.Deferred();
secondManualDeferred = aManualDeferred.then(function () {
console.log('1 started');
// We need to return this, we return a new promise which is resolved upon completion.
return wait(3500);
})
.done(function () {
console.log('1 ended');
});
thirdManualDeferred = secondManualDeferred.then(function () {
console.log('2 started');
return wait(2500);
})
.done(function () {
console.log('2 ended');
});
// Check current state
thirdManualDeferred.notify(
notifyOfProgress('thirdManualDeferred ', thirdManualDeferred)
);
// Resolve the first promise
aManualDeferred.resolve();
// Console output
// aManualDeferred pending
// secondManualDeferred pending
// 1 started
// 1 ended
// 2 started
// 2 ended
The advantage gained by this version is that we now have 3 steps which we can clearly refer to giving the advantage of being able to ask each promise for it’s state to send notifications of progress, or later manage our sequencing as needed without having to re-write the code.
Context and passing data
In the Ajax example earlier, we saw that we can pass a value to .resolve() and .fail(). If a promise is resolved with a value, it returns that value as itself.
var passingData = function () {
var def = new $.Deferred();
setTimeout(function () {
def.resolve('50');
}, 2000);
return def.promise();
};
passingData().done(function (value) {
console.log(value);
});
We can also set ‘this’ when we resolve a promise.
// Create an object
var myObject = {
myMethod: function (myString) {
console.log('myString was passed from', myString);
}
};
// Create deferred
var deferred = $.Deferred();
// deferred.done(doneCallbacks [, doneCallbacks ])
deferred.done(function (method, string) {
console.log(this); // myObject
// myObject.myMethod(myString);
this[method](string);
});
deferred.resolve.call(myObject, 'myMethod', 'the context');
=> myString was passed from the context
// We could also do this:
// deferred.resolveWith(myObject, ['myMethod', 'resolveWith']);
// but it's somewhat annoying to pass an array of arguments.
// => myString was passed from resolveWith
Best Practices
I’ve attempted to illustrate some best practices along the way but for the sake of clarity, allow me to recap them under one heading. Quite frankly most of these amount to applying other best-practices when using promises: in particular: DRY and the Single Responsibility Principle. In
name your promises
var step2 = step1.then()
separate handler functions from the promise logic by calling a named function from .then() and separate functionality into reusable bits
var someReusableFunctionality = function () {
// do something
};
step2.then(someReusableFunctionality);
when it’s logical, return a promise instead of a deferred so that nobody else can inadvertantly resolve/reject the promise
step2.then(function() {
// we don't want to give resolution / rejection powers
// to the wrong parties, so we just return the promise.
return deferred.promise();
});
don’t descend into nested callback hell or nested promise hell
By following these best practices, we can reap the most benefit from promises. We can craft decoupled applications with readable code, gain fine-gained control over asynchronous event sequencing, handle values that don’t exist yet as if they do and operations that haven’t completed yet as if they have.
jQuery Reference
I’d like to wrap-up with an overview of the jQuery API since my code examples have focused on jQuery’s implementation of promises. If you’re using a different implementation of promises, you may want to skip to the end.
Notes
deferred.always(), deferred.done(), deferred.fail() return the deferred object.
deferred.then(), deferred.when(), .promise() return a promise.
$.ajax() and $.get() return promise objects
instead of using .resolveWith() and .rejectWith(), you can call resolve with the context you want it to inherit
pass the deferred.promise() around instead of the deferred itself as the deferred object itself cannot be resolved or rejected through it.
$.Deferred()
A constructor that creates a new deferred object. Accepts an optional init function which will be executed immediately after the deferred is created.
deferred.always()
Returns the deferred object and executes attached functions upon resolution or rejection.
$.get("test.php")
// Execute regardless of resolution or success
.always(function() {
alertCompletedRequest();
});
deferred.then()
Adds handlers which will be called on resolved, rejected or in progress and returns a promise.
$.get("test.php")
// Execute regardless of resolution or success
.then(function() {
alertSuccess(),
alertFailure(),
alertProgress();
});
deferred.when()
Returns a new promise based on the completion of multiple promises. If any promise is rejected, .when() is rejected and if all promises are resolved, it is resolved. It is noteworthy that a non-promise can be passed to .when() and it will be treated as a resolved promise. Also of note is that it will return a single value only if all other promises resolve to a single value or an array, otherwise it resolves to an array.
deferred.resolve(optionalArgs) or deferred.reject(optionalArgs)
Resolve or reject the deferred object and call handler functions ( .done(), .fail(), .always(), .then() ) with any supplied arguments and pass their context to the handler they call.
$('body').on('button', 'click', function() {
// Can be passed a value which will be given to handlers
deferred.resolve();
});
deferred.promise()
Returns the promise object of the deferred. If passed a target, .promise() will attach promise methods to the target instead of creating a new object.
deferred.state()
Useful for debugging and querying the state the deferred object is in. Returns: pending, resolved or rejected.
deferred.always()
Functions or an array of functions called regardless of reject and failure.
deferred.done()
Functions or array of functions called upon resolution of the deferred object.
deferred.fail()
Functions or array of functions called upon rejection of the deferred object.
$.ajax() Performs an Ajax request and returns a promise.
Conclusion
Managing asynchronous JavaScript and writing decoupled applications can be challenging. I hope by now you have a better understanding of what promises are, how you can use them and how to avoid some of the common pitfalls. There’s still a lot of ground I haven’t covered in these two posts and for that I refer you to your libraries docs and the resources mentioned at the end of both posts. Of course, if you have questions or feedback feel free to get in touch on app.net or twitter!
In the not too distant past the primary tool available to JavaScript programmers for handling asynchronous events was the callback.
A callback is a piece of executable code that is passed as an argument to other code, which is expected to call back ( execute ) the argument at some convenient time
— Wikipedia
In other words, a function can be passed as an argument to another function to be executed when it is called.
There’s nothing inherently wrong with callbacks, but depending on which environment we are programming in there are a number of options available for managing asynchronous events. In this post my goal is to examine one set of available tools: promise objects and deferred objects. In part I, we will cover theory and semantics and in part 2 we will look at the use.
One of the keys to effectively working with asynchronous events in JavaScript is understanding that the program continues execution even when it doesn’t have the value it needs for work that is in progress. Dealing with as yet unknown values from unfinished work can make working with asynchronous events in JavaScript challenging — especially when you’re first getting started.
A classic example of this would be an XMLHttpRequest ( Ajax ). Imagine we want to:
make an Ajax request to get some data
immediately do something with that data, and then
do other things
In our program we initiate our Ajax request. The request is made but unlike with synchronous events, execution of our program isn’t stopped while the server is responding, instead the program continues running. By the time we get the response data from our Ajax request, the program has already finished execution.
Promises & Deferreds: What are they?
Promises are a programming construct that have been around since 1976. In short:
a promise represents a value that is not yet known
a deferred represents work that is not yet finished
Considered from a high level, promises in JavaScript give us the ability to write asynchronous code in a parallel manner to synchronous code. Let’s start with a diagram to get an overview of the big picture before diving into the specifics.
A promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value. Every deferred has a promise which functions as a proxy for the future result. While a promise is a value returned by an asynchronous function, a deferred can be resolved or rejected by it’s caller which separates the promise from the resolver. The promise itself can be given to any number of consumers and each will observe the resolution independently meanwhile the resolver / deferred can be given to any number of producers and the promise will be resolved by the one that first resolves it. From a semantic perspective this means that instead of calling a function ( callback ), we are able to return a value ( promise ).
Promises According to the Promise/A Proposal
The Promises /A Proposal suggests the following standard behavior and API regardless of implementation details.
A promise:
Represents the eventual value returned from the single completion of an operation
may be in one of 3 states: unfulfilled, fulfilled and failed and may only move from unfulfilled to either fulfilled or failed
has a function as a value for the property “then” ( which must return a promise )
Adds a fulfilledHandler, errorHandler, and progressHandler to be called for completion of a promise.
The value that is returned from the callback handler is the fulfillment value for the returned promise
promise’s value MUST not be changed (avoids side effects from listeners creating unanticipated behavior)
In other words, stripping out some of the nuances for a moment:
A promise serves as a proxy for a future value, has 3 possible states and needs to have a function which adds handlers for it’s states: fulfilledHandler, errorHandler and progressHandler ( optional ) and returns a new promise ( to allow chaining ) which will be resolved / rejected when the handler finishes executing.
The states and return value of a promise
A promise has 3 possible states: unfulfilled, fulfilled and failed.
unfulfilled: since a promise is a proxy for an unknown value it starts in an unfulfilled state
fulfilled: the promise is filled with the value it was waiting for
failed: if the promise was returned an exception, it is in the failed state.
A promise may only move from unfulfilled to either fulfilled or failed. Upon resolution or rejection, any observers are notified and passed the promise / value. Once the promise has been resolved or rejected neither it’s state or the resulting value can be modified.
Here is an example of what this looks like:
// Promise to be filled with future value
var futureValue = new Promise();
// .then() will return a new promise
var anotherFutureValue = futureValue.then();
// Promise state handlers ( must be a function ).
// The returned value of the fulfilled / failed handler will be the value of the promise.
futureValue.then({
// Called if/when the promise is fulfilled
fulfilledHandler: function() {},
// Called if/when the promise fails
errorHandler: function() {},
// Called for progress events (not all implementations of promises have this)
progressHandler: function() {}
});
Implementation differences & Performance
When choosing a promise library, there are a number of considerations to take into account. Not all implementations are created equal. They can differ in regards to what utilities are offered by the API, performance and even in behaviour.
Since the Promise/A proposal only outlines a proposal for the behaviour of promises and not implementation specifics, varying promise libraries have differing sets of features. All Promise/A compliant implementations have a .then() function but also have varying features in their API. Additionally, they are still able to exchange promises with each other. jQuery is the noticeable exception to the rule because its implementation of promises is not fully Promise/A compliant. The impact of this decision is documented here and discussed here.
In Promise/A compliant libraries, a thrown exception is translated into a rejection and the errorHandler() is called with the exception. In jQuery’s implementation an uncaught exception will hault the program’s execution. As a result of the differing implementation, there are interoperability problems if working with libraries which return or expect Promise/A compliant promises.
One solution to this problem is to convert jQuery promises into Promise/A compliant promises with another promise library and then use the API from the compliant library.
For example:
when($.ajax()).then()
When reading through jQuery’s decision to stick with their implementation of promises, a mention of performance considerations piqued my curiosity and I decided to do a quick performance test. I used Benchmark.js and tested the results of creating and resolving a deferred object with a success handler in .then().
The differences in performance may be negligible in a real application but in my Benchmark.js tests, when.js comes out as a clear winner. This combination of speed and the small size of the library make when.js a great choice when considering performance in the equation.
Clearly there are tradeoffs to consider when choosing a promise library. The answer to which library you should use depends on your specific use case and the needs of your project. Some implementations to start exploring are:
When.js: Fast, lightweight implementation that has a number of useful utilities and as of v2.0 has full support for asynchronous resolution.
Q.js: Runs in the browser or Node.js, offers a robust API and is fully Promise/A compliant.
RSVP: Barebones implementation that is fully Promise/A compliant.
jQuery: Not Promise/A compliant but is widely used. If you are already using jQuery in your project it’s easy to get started with and worth a look.
Conclusion
Promises provide the JavaScript developer a tool for working with asynchronous events . Now that we’ve covered some of the specifics of what promise objects and deferred objects are and how they behave, we are ready to dive into the specifics of how to work with them. In part 2, we’ll take a closer look at using promises, some common gotcha’s and some specifics of the jQuery API. In the meantime, feel free to start a conversation on App.net or Hacker News.
Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript by David Herman and part of the ‘Effective Software Development Series’ is a distillation of the type of knowledge you gain along the way — through years of being a programmer — tackling problems, asking questions and running into brick walls. In other words the lessons of experience are in here and while you may already know some of the information you will find things you don’t know.
Effective JavaScript reminds me of JavaScript: The Good Parts by Douglas Crockford in its short dense explanations of a wide variety of important concepts including scoping, functions, objects and prototypes, arrays and dictionaries, library and api design, and, concurrency. It’s not a complete language reference like David Flanagan’s JavaScript the Definitive Guide but it thoroughly covers and clearly explains nuances of how the language works along with best practices. This is the book you will find yourself reaching for in the moments you find yourself Googling for an answer of why something is or isn’t working in your JavaScript and in fact, like Douglas Crockford’s book, you should probably read Effective JavaScript more than once.
In short, Effective JavaScript is a treasure trove of knowledge packed into 200-ish pages that while geared toward imparting a mastery of the pragmatics of the language to the intermediate programmer will teach the advanced programmer at least a thing or two. Even relatively new programmers should probably attempt to read it and plan on returning to it again and again as they advance. It’s not the only book you need to become a master programmer, but it will help with mastering the language itself — which makes it an essential resource for the aspiring JavaScript programmer.
My verdict: Buy it, read it twice, give a copy to friends and return to it as a reference.
Metaprogramming Ruby: Program Like the Ruby Pros by Paolo Perrotta is a book whose style tends to be divisive. In other words, you will probably love it or hate it. Once you’ve realised that, it’s important to note that even if you fall into the category of people who hate it, it’s worth giving it a chance and pushing through. The content inside makes it worth your time.
The concepts are wrapped in a thin narrative and presented while walking through solving a series of problems in which you get the thought process and concepts along with code samples that evolve iteratively incorporating the concept being discussed. Some of the concepts covered in the book include: object model, methods, blocks, class definitions, code that writes code and Rails. The explanation of the Ruby object model is one of the best I’ve ever read.
While the narrative isn’t everyone’s preferred style ( just read through the reviews on Amazon to see what I mean ), I don’t believe it’s intended to be condescending. Rather, what it does is demonstrate problem-solving thought processes that are Ruby-oriented. This makes Metaprogramming Ruby an ideal book to read when diving into both the decision making process and the coding process rather than just finished samples of code.
The result, whether you like the style or not, is a book that teaches problem solving “the Ruby way” while explaining the Ruby notion of metaprogramming in a clear manner.