如何使用 Bluebird 在构造函数构建的“类”上承诺导出的函数

Posted

技术标签:

【中文标题】如何使用 Bluebird 在构造函数构建的“类”上承诺导出的函数【英文标题】:How to use Bluebird to promisify the exported functions on a constructor-built "class" 【发布时间】:2015-10-15 21:07:13 【问题描述】:

我有一个服务,PageService,我像这样测试(简化)...

var database = require("../database/database");
var PageService = require("./pageService");

describe("PageService", function () 
    var pageService = ;

    before(function (done) 
        pageService = new PageService(database);
    

    it("can get all Pages", function (done) 
        pageService.getAll(function (err, pages) 
            if (err) return done(err);

            pages.should.be.instanceOf(Array);
            pages.length.should.be.greaterThan(1);
            done();
    );
);

我一直在努力使用 bluebird 来承诺所有挂在 PageService 上的方法(getAll、getById、create、update、delete 等)。我看过几个关于这个主题的讨论,但大多数似乎都关心试图让构造函数返回一个承诺。我只想承诺所有挂在我通过构造函数创建的类的函数。这是 pageService = new PageService(database);我不能因为承诺而过去。

PageService 只是使用基本的构造函数模式 - 例如

self.getAll = function(next) 
    self.collection.find(, function(err, docs) 
        if (err) return next(err);

        next(null, docs);
    );
;

如果有人能告诉我正确的方法来轻松地承诺所有挂在从构造函数返回的对象上的函数,我将不胜感激。我也对我可能以错误的方式做这件事持开放态度。我对一般的承诺很陌生,欢迎指导。

更新

我通过执行以下操作获得了承诺的功能...

pageService = new PageService(database);
Promise.promisifyAll(pageService);

...但是每次我新建一个服务实例时都通过承诺来运行似乎是一种不好的做法。我想要一种承诺一次且仅一次的方式。我认识到在服务中手动返回 Promise 可能是解决方案,但希望通过 bluebird 魔法获得更优雅的东西。

【问题讨论】:

当你require它时只需promisifyAll它一次(在需要它之后立即):) 【参考方案1】:

页面服务模块:

function PageService(collection) 
    this.collection = collection;

PageService.prototype.getAll = function(next) 
    this.collection.find(, function(err, docs) 
        if (err) return next(err);
        next(null, docs);
    );
;

module.exports = PageService;

测试模块

var should = require("should");
var Promise = require("bluebird");
var database =  // mockup
    find: function (options, next) 
        next(null, ['the', 'list', 'of', 'docs']);
    
;
var PageService = require("./PageService");

Promise.promisifyAll(PageService.prototype);

describe("PageService", function () 
    var pageService;

    before(function () 
        pageService = new PageService(database);
    );

    it("can get all pages", function () 
        return pageService.getAllAsync()
        .then(function (pages) 
            pages.should.be.instanceOf(Array);
            pages.length.should.be.greaterThan(1);
        );
    );
);

【讨论】:

谢谢。问题在于“PageService.prototype.getAll = function(next) ”与我的“self.getAll = function(next) ”函数声明。关于 javascript,我还有很多东西要学。 @TimHardy 基本上是的。当您执行self.getAll = ... 时,您会在每个实例上创建该方法的新副本。因此,您必须按实例承诺。【参考方案2】:

你不应该担心每次都承诺。它所做的只是将您的回调包装在适当的承诺代码中。无需担心性能损失,这是一个完全可以接受的解决方案。

也没有其他方法可以做到这一点。这一切都归结为两种解决方案:使用Bluebirdpromisification 或手动重写您的服务以使用promises

【讨论】:

这实际上是不正确的,bluebird promisification 产生了一个非常快的函数,但它本身并不是很快(因为它通过创建一个新函数并Functioning 它进行了相当积极的优化)。对于更慢的承诺,但开销更少,有Promise.fromNode @BenjaminGruenbaum 到底有什么不正确的?您是说需要担心性能损失吗? 是的,不要一遍又一遍地承诺。在require 之后承诺一次。 好的,我错过了他在代码中而不是在require

以上是关于如何使用 Bluebird 在构造函数构建的“类”上承诺导出的函数的主要内容,如果未能解决你的问题,请参考以下文章

如何防止类中的类对象尝试在没有默认构造函数的情况下自动构建自身?

使用 Mongoose FindOne 和 Bluebird Promises 在循环中构建数组

如何在 C++ 中为矩阵类型构建构造函数

如何在 C++ 中从 dll(dll 中的构造函数)创建一些类?

构造函数重载类获取链接器错误使用DLL?

如何使用 Bluebird 承诺 NodeJS Express