0

I want to get all the hashes for a certain key from redis but because the promise takes some time my variable updates where i want to store the results is empty. I understand that this is an asynchronous problem but I can't get it to work.

client.lrange(params, (err, reply) => {
  if(err){
    callback(err)
  }
  var updates = []
  for (let i = 0; i < reply.length; i++) {
    client.hgetall("post:"+reply[i], (e, r) => {
      updates[i] = r
    })
  }
  callback(err, updates)
})

I tried applying the following concept from this answer https://stackoverflow.com/a/23667087/1617800 but it works only for a single response. I couldn't make it work in a for loop

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    console.log("5. result is: ", result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    console.log("2. callback here is the function passed as argument above...")
    // 3. Start async operation:
    setTimeout(function() {
    console.log("3. start async operation...")
    console.log("4. finished async operation, calling the callback, passing the result...")
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

Also, is there a better pattern for getting all the hashes for a series of keys from redis without going through a for loop?

Ando
  • 1,802
  • 4
  • 25
  • 47

1 Answers1

0

Here is how I did it (error handling not implemented)

First, I had to promisify the methods, because redis node will support promises in v4 (curr. v3)

const redis = require("redis");
const { promisify } = require("util");

const { client } = require('../../config/redis');
//PROMISIFIED METHODS BELOW
const hgetallAsync = promisify(client.hgetall).bind(client);

Then I used await it a for loop.

client.lrange(params, (err, reply) => {
  if(err){
    callback(err)
  }

  var updates = []

  const getAllUpdates = async _ => {
    for (let i = 0; i < reply.length; i++) {
      updates[i] = await hgetallAsync("post:"+reply[i]) //Using the promisified method
    }

    callback(err, updates)
  }

  getAllUpdates()
})

Additional resources Promises in redis node - https://github.com/NodeRedis/node-redis#promises Async/Await in loops resource which was helpful - https://zellwk.com/blog/async-await-in-loops/

Ando
  • 1,802
  • 4
  • 25
  • 47