2
\$\begingroup\$

I am working on a node.js sails.js app that handles a number of API calls and uses Bluebird for promises. The API calls have been reliable but I would like to build in handling for if they do not respond. I'm wondering if there is a good standard practice for handling timeouts (or a different approach) if the API services are down or do not respond.

Here is the code I have found/modified to work with, 15000 is a 15 second timeout on the API. Is this approach good, is there a better way?

var Promise = require('bluebird');        

return new Promise(function (resolve, reject) {
  //resolve my API call here.
})
.timeout(15000)
.cancellable()
.catch(Promise.CancellationError, function(error) {
  // ... must neatly abort the task ...
  console.log('Task cancelled', error);
})
.catch(Promise.TimeoutError, function(error) {
  // ... must neatly abort the task ...
  console.log('Task timed out', error);
});
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

The main issue I have with this code is that you're calling .timeout() on a Promise instance; by default, Promise doesn't support this - this is a Bluebird only operation.

This means that your returned Promise must evaluate true for Promise <: BluebirdPromise, which is not something that can be guaranteed in all environments (especially if you do what you've done here and omit the declaration for require('bluebird').

I'd prefer to see something like this:

const BluebirdPromise = require('bluebird');

return new BluebirdPromise(function (resolve, reject) {
  //resolve my API call here.
})
.timeout(15000)
.cancellable()
.catch(BluebirdPromise.CancellationError, function(error) {
  // ... must neatly abort the task ...
  console.log('Task cancelled', error);
})
.catch(BluebirdPromise.TimeoutError, function(error) {
  // ... must neatly abort the task ...
  console.log('Task timed out', error);
});

At the very least, this makes it clear that you aren't using the standard ES6 Promise, but that you're using a specific version from Bluebird.

I've not used the timeout and cancellable methods, so I can't speak for how you could code that better specifically, so there's probably more to say here.

\$\endgroup\$
3
  • \$\begingroup\$ Dan, really good point, I do in fact, require bluebird, and am not using ES6. This was a omission on my part, I just updated my question to include the Bluebird require, if I'm not mistaken that means I am following your suggestion. \$\endgroup\$
    – edencorbin
    Commented Jan 28, 2016 at 13:24
  • 2
    \$\begingroup\$ @edencorbin the require statement does help to somewhat meet Dan's suggestion. An important part of Dan's suggestion is changing the name of the Promise variable. This protects the code in the future. Imagine someday the codebase needs to switch to es6 Promise, the codebase has grown immensely, and a developer believes that everywhere the Promise variable is used, they can remove the require. (This would be true if your Promise use was 1:1 with es6 Promise. You aren't) TL;DR Also change the variable name. \$\endgroup\$
    – ty10r
    Commented Jan 29, 2016 at 17:20
  • \$\begingroup\$ Perfect and extremely helpful, appreciate the extra clarification, I marked this as answered. I'm still not sure if catching timeouts is a typical best practice for API calls, but this seems to be a good approach. \$\endgroup\$
    – edencorbin
    Commented Jan 29, 2016 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.