Array.push 尝试推送从 Node.js 中的 Redis 缓存接收到的对象时不起作用

Array.push doesn't work when trying to push an oject received from redis cache in Node.js

我遇到了这个问题,我想获取我的 redis 缓存中的所有键,将它们存储在一个数组中,然后将该数组与 express 一起发送给用户。问题是我在响应中收到一个空数组,其中没有任何对象。我试过使用 for (const x of ...) {...} 但那也不起作用。尝试在互联网上搜索答案,仍然没有。你能解释一下为什么会这样吗,还有我的代码。

exports.fetch = (_req, res) => {
  redis.keys("*", (err, reply) => {
    if (err) return res.json({ error: err });
    else {
      const rooms = [];
      reply.map((key) => {
        redis.get(key, (err, room) => {
          if (err) console.error(err);
          else rooms.push(room);
        });
      });

      return res.json(rooms);
    }
  });
};

更新

感谢大家的回复。

正如@boolfalse 所建议的,我使用了 async 模块并且它起作用了!

这是我更新后的代码

exports.fetch = (_req, res) => {
  redis.keys("*", (err, reply) => {
    if (err) return res.json({ error: err });
    else {
      async.map(
        reply,
        (key, cb) => {
          redis.get(key, (err, room) => {
            if (err) return cb(err);
            else return cb(null, room);
          });
        },
        (err, results) => {
          if (err) return res.json({ error: err });
          else return res.json(results);
        }
      );
    }
  });
};

但我有点不明白为什么以及它是如何工作的...

无论如何感谢您进行研究并提供您的时间

感谢用户@boolfalse 帮助我。

.

First of all, the issue in your question is that, inside the for loop, client.get is invoked with an asynchronous callback where the synchronous for loop will not wait for the asynchronous callback and hence the next line res.json({data:jobs}); is getting called immediately after the for loop before the asynchronous callbacks. At the time of the line res.json({data:jobs}); is getting invoked, the array jobs is still empty [] and getting returned with the response.

To mitigate this, you should use any promise modules like async, bluebird, ES6 Promise etc.

Modified code using async module,

    app.get('/jobs', function (req, res) {
        var jobs = [];
        client.keys('*', function (err, keys) {
            if (err) return console.log(err);
            if(keys){
                async.map(keys, function(key, cb) {
                   client.get(key, function (error, value) {
                        if (error) return cb(error);
                        var job = {};
                        job['jobId']=key;
                        job['data']=value;
                        cb(null, job);
                    }); 
                }, function (error, results) {
                   if (error) return console.log(error);
                   console.log(results);
                   res.json({data:results});
                });
            }
        });
    });

But from the Redis documentation, it is observed that usage of Keys are intended for debugging and special operations, such as changing your keyspace layout and not advisable to production environments.

Hence, I would suggest using another module called redisscan as below which uses SCAN instead of KEYS as suggested in the Redis documentation.

Something like,

    var redisScan = require('redisscan');
    var redis     = require('redis').createClient();
           
    
    redisScan({
            redis: redis,
            each_callback: function (type, key, subkey, value, cb) {
                console.log(type, key, subkey, value);
                cb();
            },
            done_callback: function (err) {
                console.log("-=-=-=-=-=--=-=-=-");
                redis.quit();
            }
        });