Using Promises In The Twilio Module For Node.js

Promises Twilio Module Node JS

Editor’s note: Are you new to using Twilio with node.js?  If so, you might want to check out this introductory blog post first.  You can also find the reference documentation for the Twilio Node module here.  Know what you’re doing?  Just npm install --save twilio to get started :)

Async Programming in node.js

One of the core design goals of node.js is to prevent blocking operations wherever possible.  This results in many of Node’s core system modules providing asynchronous interfaces that take a callback function. That function will be invoked at some point in the future when a requested operation completes, as in the  “readFile” function in Node’s file system module:

This callback function accepts two arguments – the first is an error object, which contains any error that occurred during execution of the task.  The second argument is the actual data returned from the API.  This callback style and signature is common across core Node, and in many popular modules in userland.  If you haven’t already, check out Isaac’s slides from TxJS 2013 which do a good job explaining why callbacks are standard for many APIs in Node.  You might also enjoy Isaac’s piece on designing asynchronous APIs.  In short: do not release Zalgo.

The Twilio module was originally designed with only this callback interface:

This works great if you’re only making a single request to Twilio. But if you’re going to be making multiple requests, this callback interface could potentially cause your code to march out quickly to the right, forming the dreaded pyramid of doom:

Promises, Promises

One cure (but not the only one) for the pyramid of doom is to use promises rather than callbacks for asynchronous code.  If you’re not familiar with promises, the folks over at StrongLoop have a great resource on their blog to help you wrap your head around the concept.

Promises have many other benefits beyond preventing the pyramid of doom, however. Another big bonus is that we can pass a promise value around within our application, and other parts of our program can access the result of an async call, whether or not an async operation has actually been completed. For more on why and when you might use promises, read through the StrongLoop post and the README for the Q library.

Promises in the Twilio Module

As of the 1.4.0 release of the twilio module on npm, there is now an optional promise interface you can use to consume data from the API.  The original callback interface is still 100% supported, and always will be.  The difference is that for all REST client requests, the twilio module now returns a promise (using the de facto node.js standard promise library Q), which you can use how you see fit.

Here’s a simple example of how you could make a phone call with the twilio module using the new promises interface:

In simple cases like this one, the benefits of using a promise are not obvious. In fact, for single calls to the Twilio API (like shooting off a text message or making a phone call), the callback interface is probably an easier mechanism to use. However, the benefits of using promises quickly become apparent for more complex use cases. Let’s revisit that nasty bit of Twilio REST API access code we wrote earlier to see how promises might make it a little nicer:

It might be a little longer in terms of lines of code, but it has advantages in readability. We’ve successfully flattened the pyramid, so our code now reads top to bottom instead of left to right AND top to bottom. We can consolidate our error handling logic to trigger when any of the three API calls fail (if we want). We can also easily define a function that will execute, no matter what, when all the async calls are complete.

Conclusion

As of twilio-node 1.4.0, promises (in addition to callbacks) are supported for handling asynchronous calls to the Twilio API. Promises can be useful for flattening the pyramid of doom, and for passing the results of an async operation around within an application.

If you’re just making a single call to Twilio, the callback interface is probably your best bet. If you need to pass the results of an async call around, or need to make multiple API requests, the promises interface might make sense. Either is totally fine and supported by the module.

Let us know what you think about using promises in the twilio module for Node.js at @kevinwhinnery