【问题标题】:Q.ninvoke replacement in node bluebird节点蓝鸟中的 Q.ninvoke 替换
【发布时间】:2026-01-31 09:20:02
【问题描述】:

我正在将一个项目从 Q 迁移到 bluebird。 在这个项目中,Q.invoke 被大量使用。

例如在这样的中心方法中:

repo.count = function(entity,query)  { // entity is a mongoose model
    var command = query = entity.find(query).count();
    return Q.ninvoke(command, 'exec');
};

重构此代码并返回相同“种类”承诺的最佳蓝鸟方式是什么? 阅读蓝鸟文档,似乎 promisifyAll 似乎是正确方向的一点。现在我有这个工作,但使呼叫阻塞:

repo.count = function*(entity,query)  {
    entity = bluebird.promisifyAll(entity); // this needs to be moved somewhere central
    return yield entity.find(query).count();
};

【问题讨论】:

    标签: node.js mongoose promise q bluebird


    【解决方案1】:

    我来自谷歌,接受的答案不是我想要的。我正在寻找ninvoke 的通用替代品。

    它应该看起来像这样。

    Q版:

    Q.ninvoke(redisClient, "get", "foo")
    

    蓝鸟版:

    Promise.promisify(redisClient.get, {context: redisClient})("foo")
    

    【讨论】:

    • 这是迄今为止最好的答案!
    【解决方案2】:

    嗯,你可以做几件事。最明显的是令人惊讶的“无”。

    当您不通过 exec 回调时,Mongoose 已经返回 Promises/A+ 承诺,您可以将它们同化:

    repo.count = function(entity,query)  { // entity is a mongoose model
        return entity.find(query).count().exec(); // return promise
    };
    

    您可以安全地将该承诺与 Bluebird 一起使用,它会很高兴地吸收它:

    Promise.resolve(repo.count(e, q)); // convert to bluebird promise explicitly
    
    someOtherBBPromise.then(function(query){
        return repo.count(entity, query); // `then`able assimilation
    });
    

    也就是说,最好是全面地拥有 bluebird 承诺。因为这只蓝鸟有一个非常强大的promisifyAll,它可以让你立即承诺猫鼬:

    var Promise = require("bluebird");
    var mongoose = Promise.promisifyAll(require("mongoose"));
    // everything on mongoose promisified 
    someEntity.saveAsync(); // exists and returns bluebird promise
    

    【讨论】:

    • 啊!我喜欢什么都不做!那很简单。还有一个问题:我是否需要在启动时或每次需要时都 promisfyAll mongoose?
    • @AyKarsi 在启动时,使用 bluebird 的承诺会创建 非常 快速函数(与回调版本相比开销接近于零) - 不像 Q 每次 bluebird 都会包装它们实际上为函数动态生成源代码很昂贵,但稍后会使用 JIT 编译器。虽然它是幂等的(多次调用 .promisifyAll 与调用一次的作用相同——它只实际工作一次),所以如果你多次调用它,这没什么大不了的。值得一提的是,bluebird 还与 .ninvoke 平行,称为 .fromNode
    • 感谢您的澄清!