Andrew White
Andrew White

Reputation: 610

Waiting for promise to resolve from parent function

I have a primary thread in my node application such as this:

function main_thread() {
  console.log("Starting");
  values = get_values(1);
  console.log(values);
  console.log("I expect to be after the values");
}

The get_values function calls the hgetall function using the node_redis package. This function provides a call back, but can be promisified:

function get_values(customer_id) {
  // Uses a callback for result
  new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
    console.log(result);
  });
}

This works great for promise chaining within the function, however not so well in my main thread, as I can't wait and return the value.

Here's how I'd do it in ruby, the main language I use:

def get_values(customer_id)
  return @redis_client.hgetall(customer_id)
end

How can I create a promise within a reusable function and make the main thread wait until the function returns the response from the promise?

EDIT:

It's been suggested the promise can be returned with a then chained in the main thread. However this still means any code in the main thread after after the function call executes before the then block.

EDIT 2:

After lengthy discussion with some IRL JS developer friends, it looks like trying to create a synchronous script is against the ethos of modern JS. I'm going to go back to my application design and work on making it async.

Upvotes: 3

Views: 7895

Answers (3)

crashmstr
crashmstr

Reputation: 28573

Here is a working example with async/await. I've replaced the redis with a timeout and an array for the data.

async function main_thread() {
  console.log("Starting");
  values = await get_values(1);
  console.log(`After await: ${values}`);
  console.log("I expect to be after the values");
}

async function get_values(customer_id) {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        const result = [1, 2, 3];
        console.log(`Resolving: ${result}`);
        resolve(result);
      }, 300);
  });
}

main_thread();

Further reading:

Upvotes: 3

Cody Geisler
Cody Geisler

Reputation: 8617

Simple as returning the promise (chain) from your function

function get_values(customer_id) {
  // Uses a callback for result
  return new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
    console.log(result);
  });
}

And then in your main async function or function

let result = await get_values(); or get_values.then(function(result){})

function main_thread() {
  console.log("Starting");
  values = get_values(1).then(function(values){
    console.log(values);
    console.log("I expect to be after the values");
  });
}

async function main_thread() {
  console.log("Starting");
  let values = await get_values(1);
  console.log(values);
  console.log("I expect to be after the values");
}

Upvotes: 2

Prerak Sola
Prerak Sola

Reputation: 10009

Return the promise in get_values

function get_values(customer_id) {
  // Uses a callback for result
  return new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
   reject(result);
  });
}

Now in your main thread, you could wait for it like:

function main_thread() {
  console.log("Starting");
  get_values(1).then(function(values) {
    console.log(values);
  }).catch(function(error) {
    console.error(error);
  });
}

Upvotes: 2

Related Questions