1

I know it is the most frquently asked question in javascript regarding asynchronous behaviour of functions. Still I am not able to figure out a working solution for my use case. What I am trying to do is lookup the redis cache using a key. I am using the exists function to check the key is present or not. If present then i'll return from cache if not then i'll set the key and then make a db call using this key as a db param. It seems very simple but no matter what I do i'm unable to return the value from the cache or the DB. If I make these calls outside the exist function then it works as the resolver function(graphql resolver) is an async function. This resolver functions expects a return value. So here is the code by which i'm unable to retun the value in any scenario:-

empId: async(obj, params, ctx, resolverInfo) => {

    await client.exists(obj.empId, async function(err, reply) {
      if (reply == 1) {

        return await getAsync(obj.empId).then(res => {
          console.log(res);
          return res;

        })
      } else {
        return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
          .then(iuidtest => {
            console.log(iuidtest.empid);
            return iuidtest.empid;
          })

      }
    });

    const doSomethingWith = empid => {

      console.log("empid = ", empid);

    }

I am getting the correct values in console but am unable to return. However if I directly make these calls in my resolver function i.e. outside of the redis exists function I am able to return the value.

empId: async(obj, params, ctx, resolverInfo) => {
    return await getAsync(obj.empId).then(res => {
          console.log(res);
          return res;

This way I am able to return the value from the resolver function. It would be really of great help if anybody can provide the working code for this instead of other links regarding how to return from async function using callbacks and promises. Here is another post reg the same. :- Redis async library does not have function that are in redis library for node.js Thanks in advance!

Argee
  • 1,216
  • 1
  • 12
  • 22
noob
  • 74
  • 1
  • 8
  • 1
    `await clients.exists()` will only work if that function returns a promise. According to your code it expects a callback function though, which means it doesn't return a promise and your code doesn't await anything. You need to promisify the client.exists() call. –  May 25 '20 at 12:29
  • "anybody can provide the working code for this" Welcome to Stack Overflow. Please note that this is not a free-coding service. Also, could you please explain which part you are not able to understand in [this](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call), so that others help you. – Zuckerberg May 25 '20 at 12:29
  • @Zukerberg Ok sorry I quoted that incorrectly. I am actually stuck in the part where and how to use promises with my exists function so that anyhow i am able to return the response from it. – noob May 25 '20 at 13:11
  • @ Chris G I tried promisifying the exists function but was not able to return the response. I also don't understand why this can be returned outside the exist function but not inside the callback function of it? – noob May 25 '20 at 13:13

1 Answers1

2

If client.exists returns promise, the same code can be written as below:

empId: async (obj, params, ctx, resolverInfo) => {

    const exists = await client.exists(obj.empId);

    if (exists === 1) {
      return getAsync(obj.empId);
    }

    return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
      .then(iuidtest => {
        return iuidtest.empid;
      });

  }

If client.exists only accepts callback, then the code can be written as:

empId: async (obj, params, ctx, resolverInfo) => {

    async function empIdExists(empId) {

      return new Promise(function resolver(resolve, reject) {

        client.exists(obj.empId, function(err, reply) {

          if (err) {
            reject(err);
            return;
          }

          if (reply == 1) {
            resolve(1);
            return;
          } else {
            resolve(0);
            return;

          }

        })

      });

    }

    const exists = await empIdExists(obj.empId);

    if (exists === 1) {
      return getAsync(obj.empId);
    }

    return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
      .then(iuidtest => {
        return iuidtest.empid;
      });

  }

In the second version, notice that I have wrapped the client.exists call into an async function & called using await keyword.

explorer
  • 944
  • 8
  • 18
  • This is exactly what i was looking for! Thanks a lot. When trying to promisify I was not wrapping the call into the async function and then doing the call using await for that async function. This is why the same redis and db lookups where returning in the resolver as it was async i suppose? Though i'm still far from clear about async functions and use of promises. Would be very helpful if you can suggest where to start if one is a novice. – noob May 25 '20 at 13:35
  • It is simple to understand. `async` functions are internally promise functions. `async/await` is syntatic sugar for using `Promise` constructor. If a function returns promise, it can be called using `await` keyword. If a function is an `async` function, ie: if there is `async` keyword prefixed, then you can do `.then(...)` on that function call. So, if you know that a function returns a promise, feel free to put `await` keyword when calling that function. There is nothing more to learn in there. – explorer May 26 '20 at 02:30
  • I would suggest you to write few simple promise functions & async functions and call them in both promise & async/await way to understand the dynamics. – explorer May 26 '20 at 02:36