创建一个支持回调和承诺的 Mongoose 插件

Creating a Mongoose plugin that supports callbacks AND promises

我有一个目前只支持回调的 Mongoose 插件,我计划可能将它发布到 npmjs,但我首先想确保它像现有的 Mongoose functions/methods 一样工作,它支持回调和some built in promises, and you can also specify your own promise library

我想知道在我的库中实现相同功能的最佳方法是什么,这意味着我如何支持回调 承诺?我发现 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

我在想我可以做一些基本的逻辑来查看是否提供了一个函数作为参数之一,如果是,则执行回调,如果不是,则 return 一个承诺...但我确信有一种更简单的方法可以做到这一点。

此外,对于 Promises,当我 do return promise 时,我是否应该使用 Mongoose 对象中的 Promise多数民众赞成交给插件?含义:

module.exports = Mongoose => {
    // Just verifying, should I use this?..
    const Promise = Mongoose.Promise

    return Mongoose.model( 'Foobar', new Mongoose.Schema({ /* ... */ }) )
}

更新

关于最后一个问题,关于在 returning 承诺时引用什么 Promise 对象,我尝试使用如上所述的 Mongoose.Promise,代码如下:

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 )
}

...导致错误:

/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

所以我猜这不是正确的方法...我认为 return 使用 Mongoose 配置的相同承诺库(自定义或默认.. )

我试图通过查看 findOne 函数代码来了解 Mongoose 是如何做到的,但我不太明白 return 如果没有指定回调,它是如何实现的 P.S. 我正在使用 Mongoose 4.3.7

更新

只是在修修补补,但这是可以接受的方法吗?或者这是不好的做法

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)
    })

所以我主要不想依赖特定的 promise 库,以防他们使用不同的库,但我意识到在大多数情况下,这并不重要。所以我决定坚持使用 Bluebird,并使用 asCallback 方法

这是最终结果,这是我编写的一个库,其中包含一个支持回调和承诺的函数;在一个 单独的 文件中,并且不需要特定的承诺库,使用该函数两次,一次是承诺,一次是回调:

// ./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

这似乎很有效! (感谢 tyscorp Bluebird Gitter 聊天)

就这样做

mongoose.Promise = global.Promise

就这么简单