无法find一个简单的方法出了多个asynchronous的每个节点js(帆)

所以这是交易:

我有一个对象的数组与对象的子数组

askedAdvices askedAdvice.replayAdvices 

我正在循环通过父母和foreach循环通过孩子和需要填充()两个obejcts(我使用的是帆)

孩子看起来像:

 askedAdvices = { replayAdvices : [{ bookEnd : "<ID>", user : "<ID>" }] } 

所以我的目标是用两个findOne查询来循环和填充bookEnd和user,但是我正在为callback地狱而生气。 这里是Models代码:

询问build议模型

 module.exports = { schema : false, attributes: { bookStart : { model : 'book' }, replayAdvices : { collection: 'replybookend' }, user : { model : 'user', required : true }, text : { type : "text" } } }; 

ReplyBookEnd模型

 module.exports = { schema : false, attributes: { bookEnd : { model : 'book' }, user : { model : 'user', required : true }, text : { type : "text" } } }; 

这里是方法代码:

 getAskedAdvices : function(req, res) { var queryAskedAdvices = AskedAdvices.find() .populate("replayAdvices") .populate("user") .populate("bookStart") queryAskedAdvices.exec(function callBack(err,askedAdvices){ if (!err) { askedAdvices.forEach(function(askedAdvice, i){ askedAdvice.replayAdvices.forEach(function(reply, i){ async.parallel([ function(callback) { var queryBook = Book.findOne(reply.bookEnd); queryBook.exec(function callBack(err,bookEndFound) { if (!err) { reply.bookEnd = bookEndFound; callback(); } }) }, function(callback) { var queryUser = User.findOne(reply.user) queryUser.exec(function callBack(err,userFound){ if (!err) { reply.user = userFound; callback(); } }) } ], function(err){ if (err) return next(err); return res.json(200, reply); }) }) }) } else { return res.json(401, {err:err}) } }) } 

我可以使用asynchronous库,但需要build议

谢谢大家!

正如评论中指出的,Waterline还没有很深的人口,但是你可以使用async.auto摆脱回拨地狱。 诀窍是收集所有需要查找的孩子的ID,用单个查询find他们,然后将其映射回父母身上。 代码将如下所示。

 async.auto({ // Get the askedAdvices getAskedAdvices: function(cb) { queryAskedAdvices.exec(cb); }, // Get the IDs of all child records we need to query. // Note the dependence on the `getAskedAdvices` task getChildIds: ['getAskedAdvices', function(cb, results) { // Set up an object to hold all the child IDs var childIds = {bookEndIds: [], userIds: []}; // Loop through the retrieved askedAdvice objects _.each(results.getAskedAdvices, function(askedAdvice) { // Loop through the associated replayAdvice objects _.each(askedAdvice.replayAdvices, function(replayAdvice) { childIds.bookEndIds.push(replayAdvice.bookEnd); childIds.userIds.push(replayAdvice.user); }); }); // Get rid of duplicate IDs childIds.bookEndIds = _.uniq(childIds.bookEndIds); childIds.userIds = _.uniq(childIds.userIds); // Return the list of IDs return cb(null, childIds); }], // Get the associated book records. Note that this task // relies on `getChildIds`, but will run in parallel with // the `getUsers` task getBookEnds: ['getChildIds', function(cb, results) { Book.find({id: results.getChildIds.bookEndIds}).exec(cb); }], getUsers: ['getChildIds', function(cb, results) { User.find({id: results.getChildIds.userIds}).exec(cb); }] }, function allTasksDone(err, results) { if (err) {return res.serverError(err); // Index the books and users by ID for easier lookups var books = _.indexBy(results.getBookEnds, 'id'); var users = _.indexBy(results.getUsers, 'id'); // Add the book and user objects back into the `replayAdvices` objects _.each(results.getAskedAdvices, function(askedAdvice) { _.each(askedAdvice.replayAdvices, function(replayAdvice) { replayAdvice.bookEnd = books[replayAdvice.bookEnd]; replayAdvice.user = users[replayAdvice.bookEnd]; }); }); }); 

请注意,这是假定Sails的内置Lodash和Async实例; 如果您使用的是更新版本的软件包, async.auto的用法async.auto变化(任务函数参数被切换,以便results出现在cb之前), _.keyBy . _.indexBy已被重命名为_.keyBy