Je crée une API de nœud en utilisant javascript. J'ai utilisé redis comme magasin de valeur clé. J'ai créé un client redis dans mon application et je peux obtenir des valeurs pour la clé perticulaire.
Je souhaite récupérer toutes les clés ainsi que leurs valeurs. Jusqu'à présent, je l'ai fait:
app.get('/jobs', function (req, res) {
var jobs = [];
client.keys('*', function (err, keys) {
if (err) return console.log(err);
if(keys){
for(var i=0;i<keys.length;i++){
client.get(keys[i], function (error, value) {
if (err) return console.log(err);
var job = {};
job['jobId']=keys[i];
job['data']=value;
jobs.Push(job);
});
}
console.log(jobs);
res.json({data:jobs});
}
});
});
mais je reçois toujours un tableau vide en réponse.
existe-t-il un moyen de le faire en javascript?
Merci
Tout d'abord, le problème dans votre question est que, dans la boucle for
, client.get
Est invoqué avec un asynchrone rappel où la boucle synchrone for
n'attendra pas le rappel asynchrone et donc la ligne suivante res.json({data:jobs});
est être appelé immédiatement après la boucle for
avant les rappels asynchrones. Au moment où la ligne res.json({data:jobs});
est invoquée, le tableau jobs
est toujours vide []
Et est renvoyé avec la réponse.
Pour atténuer cela, vous devez utiliser tous les modules de promesse comme async
, bluebird
, ES6 Promise
Etc.
Code modifié à l'aide du module async ,
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});
});
}
});
});
Mais à partir de
Redis
documentation , il est observé que l'utilisation des clés est destinée au débogage et aux opérations spéciales, telles que la modification de la disposition de votre espace de clés et n'est pas recommandée pour les environnements de production.
Par conséquent, je suggère d'utiliser un autre module appelé redisscan comme ci-dessous qui utilise SCAN
au lieu de KEYS
comme suggéré dans le Redis
documentation .
Quelque chose comme,
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();
}
});
Tu ne devrais jamais faire ça. Tout d'abord, il n'est pas recommandé d'utiliser KEYS *
en production. Deuxièmement, cela ne met pas à l'échelle (cluster).
Vous pouvez organiser vos entrées mises en cache dans des ensembles et rechercher les éléments dans l'ensemble, puis récupérer les clés de références. Cela facilite également l'invalidation.
Jetez un œil à quelques bonnes pratiques de stockage de données.
https://redis.io/topics/data-types-introcomment obtenir toutes les clés et valeurs en redis en javascript?
Combinaison de 2 demandes:
import * as ioredis from 'ioredis';
const redis = new ioredis({
port: redisPort,
Host: redisServer,
password: '',
db: 0
});
const keys = await redis.collection.keys('*');
const values = await redis.collection.mget(keys);
L'ordre sera le même pour les deux tableaux.
Cela obtiendra toutes les clés mais sans valeurs:
const redis = require('redis');
const client = redis.createClient();
client.keys('*', (err, keys) => {
// ...
});
Vous devez maintenant obtenir les valeurs de ces clés de manière habituelle. Par exemple:
Promise.all(keys.map(key => client.getAsync(key))).then(values => {
// ...
});
ou avec le module async
ou comme vous le souhaitez.
Vous pouvez trouver quelque chose d'utile dans ce lien
https://github.com/NodeRedis/node_redis/tree/master/examples