codelord.net

Code, Angular, iOS and more by Aviv Ben-Yosef

$q.defer: You're doing it wrong

| Comments

Using promises is tricky at first. Every newcomer to Angular will be flustered about them. It’s super easy to get lost at first between all the different nitpicks: promise chaining, $http’s special promises, the asynchronous nature of it all, etc.

One of the first questions you tackle starting to learn promises is when, if at all, should you use $q.defer()?

I used $q.defer() quite often when I first started with Angular. You know how much of that original code actually needed to use defer()? About none at all.

I realized that there was almost no reason to use defer() to create my own promises. It’s just cumbersome and error prone.

And guess what? I think that nearly everyone that uses it does it unnecessarily.

Real examples from GitHub

First, a disclaimer: this isn’t some sort of shaming. I used to write lots of code just like this. I want to show how common this problem is with real code and no handwaving.

I opened GitHub’s code search and started looking for people using $q.defer(). In the first 3 pages of results I saw about 2 actual valid use cases. Yeeeep.

Stop doing things wrong, subscribe!

You don’t need defer to create a simple-valued promise

Let’s take a look at this case:

1
2
3
4
var defer;
defer = $q.defer();
defer.resolve(['detail', 'simple']);
return defer.promise;

It’s easy to see the author just wanted to create a promise with some hard-coded value. Those 4 lines? They can just be rewritten as:

1
return $q.when(['detail', 'simple']);

Same goes for this longer case or that one. $q.when() is perfect for when you want to turn a simple value into a promise.

You don’t need defer to change the value of a promise

A lot of coders like changing $http’s special promises to work like regular ones – and rightly so. Take a look at this way of doing it:

1
2
3
4
5
var defer = $q.defer();
$http.get('options.json').success(function(result) {
  defer.resolve(result);
});
return defer.promise;

This successfully creates a promise that you can call with .then() and receive as a value the actual response body. But, through the magic of promise chaining you can simplify this:

1
2
3
return $http.get('options.json').then(function(response) {
  return response.data;
});

Promise chaining is a bit complicated, but the gist is this: inside a promise’s .then() whatever you return will be passed along to the next .then() along the chain.

This means that in our example above we’re returning a regular promise whose .then() will pass response.datasweet!

Sometimes you don’t need to do anything at all

Just about anything asynchronous is already a promise in Angular. Take a look at this:

1
2
3
4
5
var defer = $q.defer();
$timeout(function() {
  defer.resolve();
}, 5000);
return defer.promise;

The author wanted to return a promise that would get resolved once 5 seconds have passed. But guess what? $timeout already returns a promise that does just that, allowing us to write this:

1
return $timeout(function() {}, 5000);

When should you use defer?

Basically, the main reason is:

You’re converting a callback API to be promise-based: For example, if you wrap a jQuery plugin to work in Angular. Callbacks are not as fun as promises. To kickstart the promise chain and convert callbacks you have the create the first promise.

I’ve written about actually creating promises here.


You want to do Angular the right way.
You hate spending time working on a project, only to find it’s completely wrong a month later.
But, as you try to get things right, you end up staring at the blinking cursor in your IDE, not sure what to type.
Every line of code you write means making decisions, and it’s paralyzing.

You look at blog posts, tutorials, videos, but each is a bit different.
Now you need to reverse engineer every advice to see what version of Angular it was written for, how updated it is, and whether it fits the current way of doing things.

What if you knew the Angular Way of doing things?
Imagine knocking down your tasks and spending your brain cycles on your product’s core.
Wouldn’t it be nice to know Angular like a second language?

You can write modern, clean and future-ready Angular right now.
Sign up below and get more of these helpful posts, free!
Always up to date and I’ve already done all the research for you.

And be the first the hear about my Modern Angular 1.x book – writing future proof Angular right now.

Stop doing things wrong, subscribe!

Comments