2

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({ /* ... */ }) )
}

Update

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

Update

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)
    })
Community
  • 1
  • 1
Justin
  • 1,959
  • 5
  • 22
  • 40
  • I'm not sure why are you even trying to create a mongoose plugin... mangoose already support plugins doesn't it... Why does it need a plugin..? Are you going to create something like mongoose but not mongoose..?! – T J Feb 05 '16 at 06:58
  • Im trying to create a **mongoose plugin**... You think im trying to create a plugin system or something?.. Im just asking how can I create a mongoose plugin, that supports both callbacks **and** promises, like Mongoose itself does – Justin Feb 05 '16 at 17:02

2 Answers2

0

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)

Justin
  • 1,959
  • 5
  • 22
  • 40
0

just do this

mongoose.Promise = global.Promise

as simple as that

Jalasem
  • 27,261
  • 3
  • 21
  • 29