I have a Mongoose plugin that currently only supports callbacks, I plan on possibly publishing it to npmjs, but I first wanted to make sure that it works just like the existing Mongoose functions/methods, which support callbacks and some built in promises, and you can also specify your own promise library.
I wanted to know what the best way was to implement the same functionality in my library, meaning how can I support both callbacks and promises? I found a similar SO thread, but thats specific to bluebird, which even though I like to use, Id like to not assume it will be used. (Also, that article looks like it might be out-dated, as I couldnt find nodeify
in the bluebird api docs
I was thinking I could just do some basic logic to see if a function was provided as one of the parameters, if so, then execute the callback, if not, then return a promise... but im sure theres an easier way to do that.
Also, for the Promises, when I do return a promise, should I use the Promise
thats inside the Mongoose
object thats handed to the plugins? Meaning:
module.exports = Mongoose => {
// Just verifying, should I use this?..
const Promise = Mongoose.Promise
return Mongoose.model( 'Foobar', new Mongoose.Schema({ /* ... */ }) )
}
Regarding the last question, about what Promise object to reference when returning promises, I tried using the Mongoose.Promise
as stated above, code below:
module.exports = Mongoose => {
const Promise = Mongoose.Promise
const Schema = Mongoose.Schema
const fooSchema = new Schema({
name: Schema.Types.String
})
fooSchema.statics.blah = function( ) {
// Return Mongoose.Promise
return new Promise( ( res, rej ) => {
res( 'test' )
})
}
return Mongoose.model( 'Foobar', fooSchema )
}
... Which resulted in the error:
/Users/me/project/node_modules/mongoose/lib/ES6Promise.js:21
throw 'Can\'t use ES6 promise with mpromise style constructor';
^
Can't use ES6 promise with mpromise style constructor
So I'm guessing thats not the right way to go... I thought it would be a better idea to return promises using the same promise library Mongoose has configured (Custom, or default..)
I tried to see how Mongoose does it by looking at the findOne function code, but I dont quite see how it returns a promise if theres no callback specified P.S. Im using Mongoose 4.3.7
Was just tinkering around, but would this be an acceptable method? Or is it bad practice
function tester(foo, cb){
return new Promise( ( res, rej ) => {
const result = 'You said ' + foo
if( typeof cb === 'function' ){
cb( null, result )
res() // Is this needed?
}
else {
res( result )
}
})
}
tester('foo', (err, data) => {
if( err )
console.log('ERROR!',err)
else
console.log('Result:',data)
})
tester('bar')
.then( data => {
console.log('Result:',data)
})
.catch( err => {
console.log('ERROR!',err)
})
So I mainly didn't want to rely on a specific promise library, incase they were using a different one, but I realized that for the most part, it shouldnt really matter. So I decided to stick with Bluebird, and use the asCallback method
Heres the end result, this is with me coding a library with a function that supports both callbacks and promises; and in a separate file, and without requiring a specific promise library, using that function twice, once with a promise, and once with a callback:
// ./test-lib.js
'use strict'
const Promise = require( 'bluebird' )
module.exports = ( str, cb ) => {
const endResult = ( txt ) => new Promise( ( res, rej ) => res( 'You said ' + txt ) )
return endResult( str ).asCallback( cb );
}
// app.js
'use strict'
const Testlib = require('./test-lib')
Testlib('foo', ( err, data ) => {
if( err )
console.error('ERROR:',err)
else
console.log('DATA:',data)
})
Testlib('bar')
.then( data => {
console.log('DATA:',data)
})
.catch( err => {
console.error('ERROR:',err)
})
// Result:
// DATA: You said foo
// DATA: You said bar
That seems to have worked perfectly! (Thanks to tyscorp the Bluebird Gitter chat)