Node.js 如何在Nodejs循环中将值收集到数组中?

Node.js 如何在Nodejs循环中将值收集到数组中?,node.js,Node.js,我写了下面的代码,试图收集阵列中的视频,然后返回。代码是错误的,但我想不出正确的方法 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,rep

我写了下面的代码,试图收集阵列中的视频,然后返回。代码是错误的,但我想不出正确的方法

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);
});

是否有一种优雅的模式可以遵循?

大概
.hkeys
方法是异步的。这意味着您必须编写知道所有异步项何时完成的代码,这样您就可以(并且只有那时)使用累积的结果返回到最终的
res.send()

有许多方法可以跟踪所有异步操作何时完成。我最喜欢的是提示所有涉及的函数并使用
Promise.all()
。但是,由于您还没有在这段代码中使用承诺,这里有一个使用手动计数器的方法。每当启动异步任务时,递增计数器。每当完成异步任务时,减小计数器。当计数器为零时,所有异步操作都将完成:

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));
        }
      });
    });

  }
});

您可以使用
hgetall

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

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

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);  

@scimonester的可能重复-这是一个与另一个问题类似的问题,但这个答案并没有真正告诉他们如何修复这个更复杂的场景。你在寻找吗?仍然不能单独解决OP的所有问题
res.send()
必须移动。真的吗?为什么?他获取散列键,然后逐字段获取散列字段。这正是
hgetall
所做的,使用
hgetall()
是异步的,
res.send()
必须移动到
中。hgetall()
回调或
res.send()
将在
hgetall()之前被调用
已经完成了它的工作,并且总是没有结果。在第二个代码块的嵌套作用域中为两个不同的目的使用
next
是非常令人困惑的。请为其中一个选择不同的变量名。然后,在
getVideoList()
中为参数选择不同的名称。两个都是
next
让我很难理解你的代码是如何工作的。您可以使其
完成
回调
。我只是给你反馈,你写的代码很难理解和遵循,因为这个问题,它不需要这样。我建议对代码进行改进。