重构mongoose的查询

我一直在使用mongoose考虑量,我似乎无法绕过“回拨地狱”,并污染我的疑问,错误治疗。

例如,这里是我有一个路线:

var homePage = function(req, res) { var companyUrl = buildingId = req.params.company db.pmModel .findOne({ companyUrl: companyUrl }) .exec(function (err, doc) { if (err) return HandleError(req, res, err) if( !doc ) return NoResult(req, res, {msg: 'Aint there'}) console.log(doc) db.rentalModel .find({ propertyManager: doc.id }) .populate('building') .exec(function (err, rentals) { if (err) return HandleError(req, res, err) if( !doc ) return NoResult(req, res, {msg: 'Aint there'}) console.log(doc) var data = doc.toJSON() data.rentals = rentals res.render('homePage', data) }) }) } 

我的问题:有没有更简洁的方式来写这个?

所以也许你上面的仅仅是一个小例子,但是在我看来,在你的代码中没有太多的“callback地狱”(在我看来)。 但是,你当然可以重构你的代码。 只要知道这样做,就可以使其从维护的angular度来理解或遵循更加困难。

你可以做的一件事是简单地重构你的数据库层。 如果您总是发现自己查询某个集合,然后转身查询另一个集合,则可以考虑合并这些集合,或者至less包含您要查找的文档。 在关系型数据库中,您可以将这些表分开并进行合并,但是在基于文档的数据库中,将每个文档中的数据合并起来更有意义。 这允许在您的代码中更简单的查询和更简单的逻辑。

另一个解决scheme是将您的调用重构为单独的函数,并以不同的方式控制stream。 一个stream行的库,以帮助这是asynchronous ,它提供了许多帮助function,以协助JavaScript的asynchronous世界。 有很多select,但一个build议是使用瀑布function为您的情况(因为每个电话必须在下一个)。 它会看起来像这样:

 async.waterfall([ function(callback){ findCompany(companyUrl, callback); }, function(id, callback){ findPropertyManager(id, callback); } ], function (err, rentals) { res.render(rentals) }); 

您仍然需要处理每个函数中的错误,但是您甚至可以将其重构为辅助函数。 此外,你可以select自己编写一些东西来帮助控制stream程,而不是使用asynchronous。

但是,上面显示的代码是可以理解和可读的,并且只包含几个内联callback。 通过这种方式,可以减less很多事情,并且可以稍后debugging(如果事情出错)。