【问题标题】:Push data to out side async function将数据推送到外部异步功能
【发布时间】:2016-03-29 08:07:29
【问题描述】:

我仍然不能很好地处理异步函数,我有一个项目数组,我正在尝试为每个项目计算一些值并推送到异步函数之外的另一个数组。然后我想做一些统计计算并发送到前端。它是服务器端,nodejs 处理程序,我的代码:

exports.register = function (plugin, options, next) {

  function isInArray(value, array) {
    return array.indexOf(value) > -1;
  }

  function statistics(values) {
    var sum = math.sum(values);
    var max = math.max(values);
    var min = math.min(values);
    var stddev = math.std(values);
    var mean = math.mean(values);
    var count = values.length;
  }

  plugin.route({
    method: 'GET',
    path: '/statistics/{orgId}/layout/{layoutId}',
    config: {
      pre: [
        authorize(hasRole(['OPERATIONAL', 'STRATEGIC', 'LOP', 'TACTICAL']))
      ],
      handler: function (request, reply) {

        Category.find()
        .where('organization')
        .equals(request.params.orgId)
        .exec(function (err, categories) {

          var weight = [];
          var price = [];
          var volume = [];
          var thisAR = [];

          if (err || categories === null) {
            return reply(Boom.badRequest('Categoria inexistente'));
          } else {

            Location.findById(request.params.layoutId)
            .exec(function (err, layout) {
              if(err) {
                console.log(err);
              }

              var searchItems = function searchItems(category, next) {

                Item.find()
                .where('category')
                .equals(category._id)
                .exec(function (err, items) {

                  if (err) {
                    console.log(err);
                  } else {
                    var valuesToCalculate = [];
                    var itemsFiltered = [];
                    _.forEach(items, function(item) {
                      if(item.location && item.location !== null) {
                        if(isInArray(item.location.toString(), layout.contents)) {
                          itemsFiltered.push(item);
                        }
                      }
                    });
                    valuesToCalculate.push(itemsFiltered.length * category.data.weight);
                    valuesToCalculate.push(itemsFiltered.length * category.data.price);
                    valuesToCalculate.push(itemsFiltered.length * category.data.volume);
                    next(valuesToCalculate);
                  }
                });
              }

              var onFinish = function onFinish(value, err) {
                if(err) {
                  console.log(err);
                }
                console.log(value);
                thisAR.push.apply(value);
              }

              async.each(categories, searchItems, onFinish);
              console.log(thisAR);
              //var arrays = [statistics(weight), statistics(price), statistics(volume)];
              //return arrays;
            });
          }
        });
      }
    }
  });

  next();
};

【问题讨论】:

    标签: javascript arrays node.js asynchronous


    【解决方案1】:

    在这方面我有几件事很突出。首先,只有在出现错误或类别为空时才调用回复。此外,您正在尝试将非 null 值传递给 async.each 回调。根据这个:https://github.com/caolan/async#eacharr-iterator-callback,“如果没有发生错误,回调应该在没有参数或显式空参数的情况下运行”。我想你可能误解了 onFinish 回调是如何与 async.each 一起工作的。它不是为每个项目调用的,它是在 all 的迭代器函数完成时调用的。因此,与其在 onFinish 中将项目推送到 thisAR 上,不如在 searchItems 中这样做。我认为这应该可行:

    exports.register = function (plugin, options, next) {
    
      function isInArray(value, array) {
        return array.indexOf(value) > -1;
      }
    
      function statistics(values) {
        var sum = math.sum(values);
        var max = math.max(values);
        var min = math.min(values);
        var stddev = math.std(values);
        var mean = math.mean(values);
        var count = values.length;
      }
    
      plugin.route({
        method: 'GET',
        path: '/statistics/{orgId}/layout/{layoutId}',
        config: {
          pre: [
            authorize(hasRole(['OPERATIONAL', 'STRATEGIC', 'LOP', 'TACTICAL']))
          ],
          handler: function (request, reply) {
    
            Category.find()
            .where('organization')
            .equals(request.params.orgId)
            .exec(function (err, categories) {
    
              var weight = [];
              var price = [];
              var volume = [];
              var thisAR = [];
    
              if (err || categories === null) {
                return reply(Boom.badRequest('Categoria inexistente'));
              } else {
    
                Location.findById(request.params.layoutId)
                .exec(function (err, layout) {
                  if(err) {
                    console.log(err);
                  }
    
                  var searchItems = function searchItems(category, next) {
    
                    Item.find()
                    .where('category')
                    .equals(category._id)
                    .exec(function (err, items) {
    
                      if (err) {
                        console.log(err);
                      } else {
                        var valuesToCalculate = [];
                        var itemsFiltered = [];
                        _.forEach(items, function(item) {
                          if(item.location && item.location !== null) {
                            if(isInArray(item.location.toString(), layout.contents)) {
                              itemsFiltered.push(item);
                            }
                          }
                        });
                        valuesToCalculate.push(itemsFiltered.length * category.data.weight);
                        valuesToCalculate.push(itemsFiltered.length * category.data.price);
                        valuesToCalculate.push(itemsFiltered.length * category.data.volume);
                        thisAR.push.apply(valuesToCalculate);
                      }
                      next(err);
                    });
                  }
    
                  var onFinish = function onFinish(err) {
                    if(err) {
                      console.log(err);
                    }
                    console.log(thisAR);
                    // call reply here
                  }
    
                  async.each(categories, searchItems, onFinish);
                  console.log(thisAR);
                  //var arrays = [statistics(weight), statistics(price), statistics(volume)];
                  //return arrays;
                });
              }
            });
          }
        }
      });
    
      next();
    }; 
    

    【讨论】:

    • 感谢@MikeAtkins 的重播,是的,我完全误解了 onFinish 函数的作用。你说的我试过了,但是onFinish函数中的console.log是空的。我错过了什么?
    • 我不确定。旁注:我将调用 next 移出 else 正文,并添加了一个 err 作为 next 的参数,以便更好地处理错误。您根本没有看到任何控制台消息吗?
    • 你确定 items 不为空吗?
    • 有了@brian baker 的评论,它的工作很完美。谢谢!!
    【解决方案2】:

    由于我是新手,因此无法发表评论,但似乎仅删除 thisAR.push.apply(valuesToCalculate); 中的 .apply 就会将完整的数组返回到您的 console.log。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      • 2020-12-19
      • 2022-06-13
      • 2021-07-16
      相关资源
      最近更新 更多