NodeJS中解析对象数组的递归函数

时间:2014-07-17 12:38:25

标签: javascript node.js mongodb recursion

我有这样的NodeJS控制器:

     var importOrders = function (req, res, next) {

    var orders = req.body;

    var processOrder = function (order) {
        if(i<orders.length-1){
            try {
                if (orders[i].Order.Company === "Mondial") {
                    parseMondial(db, orders[i].Order, processOrder(orders[i++]), log);
                }
            } catch (error) {
                next(error);
                log.error('orders', 'error Importing', error, order);
            }
        }
    };

    var i = 0;
    processOrder(orders[i]);
    res.send(orders.length);

};

在parseMondial内部,我使用promises在mongoDB中进行了大量查询,但这会查询它们之间的关系。

这不起作用,因为我需要在parseMondial内完成进程以进行下一个对象解析,但不等待。 我不知道我怎么能这样做..任何帮助它的好处。

2 个答案:

答案 0 :(得分:0)

我把一些javascript扔进了一个plunkr来模仿它会是什么样子。只需打开控制台并运行代码即可。您应该看到它通过并返回Mondial Orders的数据。

http://plnkr.co/edit/22qyZox6WJLsv5qS2n11?p=preview

var req = {};
//Emulate orders in req
req.body = [
    {Order: {Type: 'Mondo Cool', Company: 'Mondial'}},
    {Order: {Type: 'Moo', Company: 'Cow Guys'}},
    {Order: {Type: 'Woof', Company: 'Dog Guys'}},
    {Order: {Type: 'Mondo Bacon', Company: 'Mondial'}},
    {Order: {Type: 'Bawk Bawk', Company: 'Cat Guys'}},
    {Order: {Type: 'Mondo Cheese', Company: 'Mondial'}},
];

//Fill in a mock db
var db = 'mockDb';

//Import Orders
var importOrders = function(req, res, next){
    var orders = req.body;
    var processOrder = function () {
      if(i < orders.length){
          if(orders[i].Order.Company === "Mondial"){
            parseMondial(db, orders[i].Order, processOrder);
            i++;
          } else{
            i++;
            processOrder();
          }
      } else {
        //Mocks ending the loop and perform final res.send()
         console.log('res.send');
      }
    };
    var i = 0;
    processOrder();
};

//Emulates parseMondial and async request/queries
function parseMondial(db,order,callback,log){
  //Do something with order asyncrounously
  setTimeout(function(){
    console.log(order);
    console.log('Did a query and waited for the response ' + order.Company);
    callback();
  }, 1000);
}

//Mock making a req to importOrders
importOrders(req,null,null);  

一旦parseMondial中的代码完成,您就可以调用回调,如果需要,可以传递数据。但是,它可能没有引用i或parseMondial中的订单,所以为了安全起见,我处理了传递命令并在parseMondial之外迭代索引。

传入processOrders()不是回调。传递processOrders将其作为一个函数提供,可以在parseMondial结束时调用。

我拿出了一些try / catch内容,只是为了让代码更易于阅读和用于您的目的。

答案 1 :(得分:0)

最后我这样做了:

var importOrders = function (req, res, next) {

    var orders = req.body;
    var i = 0;

    var doNext = function () {
        i++;
        processOrder();
    };

    var processOrder = function () {
        if (i < orders.length) {
            try {
                if (orders[i].Order.Company === "Mondial") {
                    parseMondial(db, orders[i], doNext, log);
                }
            } catch (error) {
                next(error);
                log.error('orders', 'error Importing', error, orders[i].Order);
            }
        }else{
            res.send({total:i});
        }
    };
    processOrder();
};

在parseMondial内部,当我完成所有任务时,我做了calback();