使用Bluebird进行Mongoose承诺的正确方法是什么?

时间:2016-11-11 15:50:56

标签: mongoose bluebird

我一直在阅读文档和文章,每个人似乎都在描述将Mongoose和Bluebird结合使用的不同方式。甚至官方的Mongoose文档says something和Bluebird文档都说another thing

据Mongoose说:

mongoose.Promise = require('bluebird');

据蓝鸟说:

var Promise = require("bluebird");
Promise.promisifyAll(require("mongoose"));

所以根据我的理解,如果您选择Mongoose方式,示例查询将是:

User.findById('someId')
    .then(function(){
        // do stuff
    })
    .catch(function(err){
        // handle error
    })

但是在Mongoose的文档中它也说:

  

Mongoose查询不是承诺。但是,它们对yield和async / await都有.then()函数。如果您需要完全成熟的承诺,请使用.exec()函数。

那么在这种情况下,.then是否高于承诺?

如果你选择Bluebird方式:

User.findById('someId')
    .execAsync()
    .then(function(){
        // do stuff
    })
    .catch(function(err){
        // handle error
    })

或者甚至可以跳过execAsync(),而是从findByIdAsync开始。

真的与不同的文档混淆了。如果有人能对此有所了解,我会很感激。

3 个答案:

答案 0 :(得分:22)

选择Mongoose方式:

import socket
import os

def open_connection():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(("0.0.0.0", 9000))
    sock.listen(1)
    client, address = sock.accept()
    sock.close()
    return client

def file_transfer(client):
    path = raw_input("Enter path of file on client: ")
    local_path = os.path.join(os.getcwd(), os.path.basename(path))
    print 'will write to local file', local_path
    client.send(path)
    with open(local_path + '.tmp', 'wb') as outfile:
        while True:
            block = client.recv(1024)
            if not block:
                break
            outfile.write(block)
    os.rename(local_path + '.tmp', local_path)
    print 'wrote', os.stat(local_path).st_size, 'bytes'

def main():
    client = open_connection()
    file_transfer(client)
    client.close()



if __name__ == "__main__":
    main()

那是因为Mongoose 已经支持承诺(除了还接受回调);上面的代码只是替换了Bluebird的Mongoose自己的promise库(mpromise)(可能更快,更好的测试,并且有更多的实用功能可用)。

Bluebird的mongoose.Promise = require('bluebird'); 旨在允许使用promises(纯粹基于回调的函数)的代码返回promises。

答案 1 :(得分:8)

来自Bluebird doc

Promise.promisifyAll(
    Object target,
    [Object {
        suffix: String="Async",
        multiArgs: boolean=false,
        filter: boolean function(String name, function func, Object target, boolean passesDefaultFilter),
        promisifier: function(function originalFunction, function defaultPromisifier)
    } options] ) -> Object

正如你所看到的,默认情况下,promisifyAll会添加后缀'Asyns',所以如果你使用这种宣传方式:

var Promise = require("bluebird");
Promise.promisifyAll(require("mongoose"));

User.findById的异步版本为User.findByIdAsync

mongoose.Promise

怎么样?

然后您使用承诺库,如

mongoose.Promise = require('bluebird');

内置的承诺机制由库替换:query.exec().constructor替换为require('bluebird'),因此代替.exec()作为返回承诺,您可以直接将蓝鸟概率用于mongoose查询,例如

User.findOne({}).then(function(user){
    // ..
})  

答案 2 :(得分:1)

对于那些使用TypeScript的人来说,正确的方法是:

(<any>mongoose).Promise = YOUR_PROMISE;

来自文档:

Typescript does not allow assigning properties of imported modules. To avoid compile errors use one of the options below in your code:

(<any>mongoose).Promise = YOUR_PROMISE;

require('mongoose').Promise = YOUR_PROMISE;

import mongoose = require('mongoose'); mongoose.Promise = YOUR_PROMISE;