环回:对loopback api进行同步调用

时间:2016-02-26 13:32:26

标签: javascript node.js loopbackjs

我想对我使用loopback设计的API之一进行同步调用。这是我的代码:

router.get('/friends', function(req, res, Array) {
    var friendsList = []
    for(var counter=0;counter<length;counter++){
                  Model.findById(Array[counter].Id,function(err, record) {
                    if(record){
                        friendsList.push(record);
                    }
                  });
                }
                res.status(200).json(friendsList);
});

现在我在数组之前获得响应, friendList 正在完全填充。我想让它同步并获得正确的响应。我该怎么办?

谢谢!

4 个答案:

答案 0 :(得分:3)

一种简单的方法是

  • 将变量设置为length
  • 每次调用回调时,将此变量减少1
  • 当它达到零时,您已经处理了最终回调
  • 在回调中,拨打res.status...

像这样:

router.get('/friends', function(req, res, array) {
    var friendsList = [];
    var remaining = length;
    for(var counter=0;counter<length;counter++){
        Model.findById(array[counter].Id, function(err, record) {
            if (record){
                friendsList.push(record);
            }
            remaining -= 1;
            if (remaining == 0) {
                res.status(200).json(friendsList);
            }
        });
    }
});

为了完整性...因为您正在使用nodejs ...使用(本机)Promise和arrow function语法

router.get('/friends', (req, res, array) =>
    Promise.all(array.map(item => 
        new Promise((resolve, reject) => 
            Model.findById(item.Id, (err, record) => 
                resolve(record || undefined)
            )
        )
    ))
    .then(friendsList => 
        res.status(200).json(friendsList.filter(item => 
            item !== undefined
        ))
    )
);

答案 1 :(得分:1)

我使用asyncunderscore模块

var async = require('async');
var _ = require('underscore');

router.get('/friends', function(req, res, Array) {
    var friendsList = [];
    var waterfallFunctions = [];
    _.each(Array, function(element) {
      waterfallFunctions.push( function(next) {
        Model.findById(element.Id,function(err, record) {
          if (err) return next(err);

          if(record){
            friendsList.push(record);
          }

          next();
        });
      });
    });

    //async waterfall calls the functions in the array in order.
    async.waterfall(waterfallFunctions, function (err) {
      if (err) return res.status(500);

      res.status(200).json(friendsList);
    });

});

答案 2 :(得分:0)

使用Promise和Mongoose中的SkipWhile运算符:

reeks.SkipWhile(n => n >= 1000 || n <= 10).TakeWhile(n => n < 1000 && n > 10)

$in从数组中选择第一个router.get('/friends', function(req, res, arr) { var promise = Model.find({ _id: { $in: arr.slice(0, length).map(function (e) { return e.Id }) } }).exec() promise.then(function (friendsList) { res.status(200).json(friendsList) }) }) 元素。 arr.slice创建一个查询,这比执行多个length查询更有效。 Model.find运算符接受一组id来进行查找。 findById创建一个承诺,使用$in解决。

答案 3 :(得分:0)

你应该等到N个findById调用完成,所以解决方案是制作一个promises数组并使用Promise.all方法。

router.get('/friends', function(req, res, Array) {
    var friendsList = []
    var friendsPromises = []

    for (var counter=0; counter<length; counter++) {
        var friend = Model.findById(Array[counter].Id;
        friendsList.push(friend)

        friend.then(function(record) {
            if (record) {
                friendsList.push(record);
            }
        })
    }

    Promise.all(friendsPromises).then(function(){
        res.status(200).json(friendsList);    
    })
});