【问题标题】:How to collect the value to an array in Nodejs loop?如何将值收集到 Nodejs 循环中的数组中?
【发布时间】:2014-11-25 15:08:06
【问题描述】:

我编写了下面的代码,试图将视频收集到一个数组中然后返回。代码是错误的但我想不出正确的方法来做到这一点。

var redis = require('redis');
var client = redis.createClient();

app.get('/topvideos', function(req, res){
  res.type('application/json');
  var topvideos = [];

  client.hkeys("topvideos", function(err,replies) {
    console.log("Results for video:");
    console.log(replies.length + " videos:");

    replies.forEach(function (reply, i) {

      client.hget("topvideos",i, function (err, reply) {
        console.log(i + ": " + reply );
        topvideos.push(reply);
      });
    });

  }
  var string = JSON.stringify(topvideos)
  res.send(string);
});

有没有我可以遵循的优雅模式?

【问题讨论】:

标签: node.js


【解决方案1】:

大概.hkeys 方法是异步的。这意味着您必须编写知道所有异步项目何时完成的代码,这样您才能(并且只有在那时)才能获得最终的 res.send() 并累积结果。

有很多方法可以跟踪所有异步操作何时完成。我最喜欢的是承诺所有涉及的功能并使用Promise.all()。但是,由于您尚未在此代码中使用 Promise,因此这里有一个使用手动计数器的方法。每当您启动异步任务时增加计数器。每当您完成异步任务时递减计数器。当计数器为零时,所有异步操作都完成:

var redis = require('redis');
var client = redis.createClient();

app.get('/topvideos', function(req, res){
  res.type('application/json');
  var topvideos = [];
  var cntRemaining = 0;

  client.hkeys("topvideos", function(err,replies) {
    console.log("Results for video:");
    console.log(replies.length + " videos:");

    replies.forEach(function (reply, i) {
      ++cntRemaining;

      client.hget("topvideos",i, function (err, reply) {
        console.log(i + ": " + reply );
        topvideos.push(reply);
        --cntRemaining;
        if (cntRemaining === 0) {
           res.send(JSON.stringify(topvideos));
        }
      });
    });

  }
});

【讨论】:

    【解决方案2】:

    你可以使用hgetall

    client.hgetall("topvideos", function(err, videos){
      var keys = Object.keys(videos);
      res.send(JSON.stringify(keys.map(function(key){return videos[key];})));
    });
    

    Documentation

    另外,我建议使用单独的函数来包装所有单独的任务,例如:

    var async = require('async');
    
    function getKeyValueMap(obj) {
       return function(key, next) {
         return next(null, obj[key]);
       }
    }
    
    function getValues(obj, next) {
        async.map(Object.keys(obj), getKeyValueMap(obj), next);
    }
    
    function getVideoList(next) {
      client.hgetall("topvideos", function(err, videos){
        if (err) return next(null, []);
        getValues(videos, next);
      });
    }
    
    function response(err, data) {
      if (err) return res.send(err.message)
      return res.send(JSON.stringify(data));
    }
    
    getVideoList(response);  
    

    【讨论】:

    • 仍然不能单独解决 OP 的所有问题。 res.send() 必须移动。
    • 真的吗?为什么?他获取哈希键,然后逐字段获取哈希字段。这正是hgetall 的作用
    • 假设hgetall() 是异步的,res.send() 必须在.hgetall() 回调中移动,否则res.send() 将在hgetall() 完成工作之前被调用并且总是没有结果。
    • 在第二个代码块的嵌套范围内将next 用于两个不同的目的是非常令人困惑的。请为其中一个选择不同的变量名称。
    • 然后,为getVideoList() 中的参数选择一个不同的名称。两者都是next 让我很难理解你的代码是如何工作的。您可以将其设为donecallback。我只是给你反馈,因为这个问题,你编写的代码很难理解和遵循,而且不一定是这样。我建议对代码进行改进。
    猜你喜欢
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 2011-03-04
    • 2022-11-19
    • 2022-06-15
    • 1970-01-01
    相关资源
    最近更新 更多