6130

Create an api which accepts a callback, and also returns a promise

So I'm trying to upgrade an existing api to support promises, but I want to maintain backwards compatibility. So, let's say this is my api:

module.exports = { deliverPost: function(callback) { someAsyncFunction(function(err) { if (err) console.log(err); callback(err); }); } }

That's great, I can call it and pass a callback, and everything works.

Now we do the same thing with promises:

var q = require('q'); module.exports = { deliverPost: function() { return q.nfcall(someAsyncFunction).catch(function(err) { console.log(err); throw err; }); } }

Great, now it returns a promise, but my problem is, any old clients of this api expect to be able to pass in a callback!

So what I really need is something like this:

var q = require('q'); module.exports = { deliverPost: function(callback) { return q.nfcall(someAsyncFunction).catch(function(err) { console.log(err); throw err; }).attachNodeStyleCallback(callback); } }

So new callers can leverage the promise support, but everything still works if you pass in a callback.

This is a pattern used by, e.g. jQuery.ajax -- how can I do the same with Q.js?

Here's an implementation of attachNodeStyleCallback for reference:

q.makePromise.prototype.attachNodeStyleCallback = function(callback) { if (!callback) return this; return this.then(function(result) { callback(null, result); return result; }, function(err) { callback(err); throw err; }) }

Answer1:

The answer is to use promise.nodeify:

var q = require('q'); module.exports = { deliverPost: function(callback) { return q.nfcall(someAsyncFunction).catch(function(err) { console.log(err); throw err; }).nodeify(callback); } }

Answer2:

You could just test for a callback and run the callback code if it is present:

var q = require('q'); module.exports = { deliverPost: function(callback) { if(typeof callback === 'function'){ someAsyncFunction(function(err) { if (err) console.log(err); callback(err); }); }else{ return q.nfcall(someAsyncFunction).catch(function(err) { console.log(err); throw err; }); } }

Recommend

  • how to connect to a mysql database through eclipse
  • Update a record where _id = :id with Mongoose
  • Easy way to convert a Bitmap and Png Image to text and vice versa
  • Convert C# statements including NSubstitute code to VB.net
  • Generic classes with Collection getter of other types
  • Ionic storage “get” returns null only on the second call within method
  • SQL - Select lowest values with group by and order by?
  • multidatatrigger with multibinding in ControlTemplate.Triggers
  • Cypher - matching two different possible paths and return both
  • Cloud Code function running twice
  • JSR-330 support in Picocontainer : @Inject … @Named(\"xxx)
  • Creating a DropDownList
  • Who propagate bugfixes across branches (corporate development)?
  • Thread safety of a fluent like class using clone() and non final fields
  • Needing to do .toArray() to get output of mongodb .find() on key name not value
  • Converting a WriteableBitmap image ToArray in UWP
  • MongoError: Incorrect arguments
  • Scrapy recursive link crawler
  • formatting the colorbar ticklabels with SymLogNorm normalization in matplotlib
  • Why value captured by reference in lambda is broken? [duplicate]
  • Is there a amazon webstore API for customers?
  • How to get a value (ex: baseURL) in every Karate feature?
  • How to recover from a Spring Social ExpiredAuthorizationException
  • Obtain ObjectIdHex value from mgo query
  • Incrementing object id automatically JS constructor (static method and variable)
  • javascript inside java/jsp code
  • ILMerge & Keep Assembly Name
  • Perl system calls when running as another user using sudo
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • Upload files with Ajax and Jquery
  • Large data - storage and query
  • WOWZA + RTMP + HTML5 Playback?
  • How to pass list parameters for each object using Spring MVC?
  • AngularJs get employee from factory
  • Proper way to use connect-multiparty with express.js?
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • LevelDB C iterator
  • Busy indicator not showing up in wpf window [duplicate]
  • Why do underscore prefixed variables exist?