环回:对环回 API 进行同步调用

Loopback : Making synchronous call to loopback api

本文关键字:同步 调用 API 环回      更新时间:2023-09-26

我想对我使用环回设计的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 正在完全填充。我想使它同步并获得正确的响应。我该怎么办?

谢谢!

一个简单的方法是

  • 将变量设置为 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...使用(本机)承诺和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
        ))
    )
);

我会使用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);
    });
});

在 Mongoose 中使用 Promise 和 $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创建单个查询,这比执行多个findById查询更有效。 $in运算符接受要对其执行查找的 id 数组。 .exec()创建一个承诺,该承诺通过.then(...)解决。

你应该等到 N findById 调用完成,所以解决方案是做出一系列承诺并使用 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);    
    })
});