找不到每个节点js(sails)的多重异步的简单方法

时间:2016-05-03 08:28:39

标签: node.js asynchronous sails.js

所以这是交易:

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

askedAdvices 
   askedAdvice.replayAdvices

我正在循环通过父级和foreach循环通过子级并需要填充()两个obejcts(我正在使用风帆)

孩子看起来像:

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

所以我的目标是使用两个findOne查询来循环和填充bookEnd和user,但是我对回调地狱感到很生气。 这是模型代码:

AskedAdvices Model

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})
        }
    })
}

我可以使用异步库但需要建议

谢谢大家!

1 个答案:

答案 0 :(得分:1)

正如评论中指出的那样,Waterline还没有深入人口,但你可以使用async.auto摆脱回调地狱。诀窍是收集您需要查找的所有子项的ID,通过单个查询找到它们,然后将它们映射回父项。代码看起来如下所示。

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&#39;内置Lodash和Async实例;如果你正在使用这些软件包的较新版本,async.auto的使用会略有改变(任务函数参数会被切换,以便resultscb之前),{{1 }已重命名为_.indexBy