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();
}
});
我遇到了这个问题,我想获取我的 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 synchronousfor
loop will not wait for the asynchronous callback and hence the next lineres.json({data:jobs});
is getting called immediately after thefor
loop before the asynchronous callbacks. At the time of the lineres.json({data:jobs});
is getting invoked, the arrayjobs
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 ofKEYS
as suggested in theRedis
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();
}
});