1

I have the following async function

export default async function getUserNames(id: string[]): Promise<string[]> {
    let userNames: string[] = [];
    // We do some stuff here like calling a service, etc...

    return userNames;
}

On a different typescript file, I am importing the getuserNames function and trying to call it like this:

const promiseResult = getUserNames(idList)
        .then(result => {
            return result;
        })
        .catch(error => {
            return undefined;
        });

    if (promiseResult) {
        // Do something else here.
    }

However, the promiseResult type is of Promise instead of string[] which is what I am expecting. How can I call the getuserNames function and when it is done, the actual string[] is returned to the promiseResult variable?

EDIT Is it accepted to do something like this?

let varB: string[];
const promiseResult = getUserNames(idList)
        .then(result => {
            varB = result;
        })
        .catch(error => {
            varB = undefined;
        });

if (varB) {
        // Do something else here.
    }

Lastly, please notice that the function that calls getUserNames is not defined as async and I can't change that.

user3587624
  • 1,427
  • 5
  • 29
  • 60
  • 2
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – str Mar 27 '19 at 17:04

3 Answers3

3

If you want to get access to the value that the promise resolves to, your only options are

1) use the promise's .then callback

getUserNames(idList)
  .then(result => {
    // Do something else here.
  })

2) Put the code in an async function and use the await keyword:

async function someFunction () {
  const result = await getUserNames(idList);
  // Do something else here.
}

Note that since all async functions return promises, someFunction will return a promise in this example.

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • Just want to add that the `async` function will return a promise aswell – gbalduzzi Mar 27 '19 at 17:07
  • The second option I think is not doable for me because within the function that I am calling getUserNames is not an async function and I can't change that. In the first option, why when I do *return result* inside the .then(result ...) can I assign the result to a variable that is out of the getUserNames result? something similar to what I have done in my edition of the main post. – user3587624 Mar 27 '19 at 17:14
  • Just to clarify: If I try to do awai getUserNames within the function that I am trying to call getuserNames I get an error that says 'await' expression is only allowed within an async function. – user3587624 Mar 27 '19 at 17:18
  • 1
    `why when I do return result inside the .then(result ...) can I assign the result to a variable that is out of the getUserNames result?` Assigning to a variable like that is legal javascript but almost certainly not what you want to do. The promise will resolve at some unknown time in the future. Any code that to interact with the result synchronously will fail, because the value doesn't exist yet. If you want to wait for the value to be available, then your only options are the .then callback or await. And yes, await can only be used in an async function. – Nicholas Tower Mar 27 '19 at 17:25
  • Thanks, I will marl your response as the valid one given that you have enumerated here the two possible options. – user3587624 Mar 27 '19 at 17:33
0

getUserNames does return a promise<string[]> that's exactly what its signature says.

You should perform your if (result) inside the then

Or you could use the new await keyword which will make sure the promise is resolved before it's assigned to promiseResult In this case, wrap your await inside a try/catch.

Swann
  • 2,413
  • 2
  • 20
  • 28
  • I see what you mean. Then it is not possible to do anything else out of the if (result) block. All the dependent code needs to go in there, right? – user3587624 Mar 27 '19 at 17:21
0

You not need to use async/await in your code.

/**
 * async data fetcher
 * @param {String} url 
 * @param {Object} options 
 * @returns {Promise}
 */
const fetch = (url, options) => {
  return new Promise((resolve, reject) => {
    fetch(url, options)
      .then((response) => {
        if (response.ok) {
          return resolve(response.json)
        }
        return reject(response.json)
      })
      .catch((error) => reject({ error }))
  })
}

/**
 * async fetch wrapper, returns a Promise
 * @param {NUmber} id 
 * @returns {Promise}
 */
const getUserNames = (id) => {
  return fetch('www.yourapi.com/get_user_names', { params: { id } })
}

const idList = [1, 2, 3]
// so, your code also will be asyncronious too:
Promise.all([getUserNames(idList)]).then((promiseResult) => {
  if (promiseResult) {
    // Do something else here.
  }
})
Sergio Belevskij
  • 2,478
  • 25
  • 24