Home > database >  Return Promise<Class> from async method
Return Promise<Class> from async method

Time:10-26

I'm learning typescript and messing around with an API endpoint, I've created a method which takes a value, makes a request to an external API and gets the data, populates the model PortalDetail and returns it back to the front end.

However, the returned data is always null. I have checked the portalUrl and the value exists, so I'm not sure what I'm doing wrong here:

Here is the code in question:

const CheckUri = async (organisationCode: string): Promise<PortalDetail | null> => {

    await fetch(`${uris.appCode}${organisationCode}`)
        .then(async (data) => {
            const portalUrl = await data
                .text()
                .then((html) => html)
                .catch(() => null)

            console.log(portalUrl); // This has a value
            console.log(data); // So does this

            if (data?.status === 200 && portalUrl) {

                console.log("inside if"); // This also gets printed

                return new PortalDetail(portalUrl, organisationCode);
            }
        })
        .catch(() => {

        })
        .finally(() => {

        })

    return null;

}

Here is the code calling the method:

const CheckOrgnisationCode = async (orgCode: string) => {

    if (!orgCode || orgCode.includes(' ')) {
      return;
    }

    console.log("before checkuri method")

    var portalDetails = await CheckUri(orgCode);

    console.log("finiahes ");
    

    console.log(portalDetails);

    if (portalDetails?.portalUrl) {
      await StoreData(saved.portalURL, portalDetails?.portalUrl);
      await StoreData(saved.portalCode, orgCode);
    }

  }

Can someone please explain where I'm going wrong?

CodePudding user response:

You are always returning null, no matter the result of the fetch call - see the last line of the function:

return null

You have two options:

  1. Return the fetch call directly:
return fetch(...);
  1. Store the fetch call return value in a variable and return that variable:
const response = await fetch(...);
return response;

Both options are equivalent.

And since you are using an async function, you can use try/catch like in sync code like in the following really simplified example:

try {
  const response = await fetch('url');
  const html = await response.text();

  // note: fetch doesn't throw for status codes >= 400
  if (response?.status === 200) {
    return html;
  } else {
    throw Error('Server error');
  }
} catch (error) {
  return null
}

CodePudding user response:

You are confused with async/await and Promises.

  1. Never call await & .then simultaneously on a Promise
  2. Use try/catch inside async functions when you want to handle errors.
const CheckUri = async (organisationCode: string): Promise<PortalDetail | null> => {
  try {
    const resp = await fetch(`${uris.appCode}${organisationCode}`)
    if (!resp.ok) { // almost same as resp.status !== 200
      throw resp
      // or

      // const text = await resp.text()
      // throw text
    }
    const portalUrl = await resp.text()

    return new PortalDetail(portalUrl, organisationCode)
  } catch (err) {
    // console.error(err)
    return null
  }
}

CodePudding user response:

You are mixing promise.then with async/await. And it usually it gets to such results. Choose one - async/await is more readable.

The issue is in the first .then you return something. You await the call but you do not assign it to anything

.then(async (data) {
  if (data?.status === 200 && portalUrl) {
    //this return will not return the result to the CheckUri  
    return new PortalDetail(portalUrl, organisationCode);
  }
});

Here is what you should to to your code

const CheckUri = async (organisationCode: string): Promise<PortalDetail | null> => {

    const RESLUT = await fetch(`${uris.appCode}${organisationCode}`) 
        //...

    return RESULT;

Here is your code with async.await which I believe is more readable.

const CheckUri = async (organisationCode: string): Promise<PortalDetail | null> => {

    try {
        const fetchResult = await fetch(`${uris.appCode}${organisationCode}`);
        const portalUrl = await fetchResult.text();

        if (fetchResult.status === 200 && portalUrl) {
          return new PortalDetail(portalUrl, organisationCode);
        }
        else {
            return null;
        }

    } catch(e) {
       //handle the error
       console.error("We couldn't check the URI", e);
       return null
    } finally {
        //do the cleanup logic
    }
}

Typescript playground here

  • Related