skip to Main Content

I have a problem that I don’t understand how to solve, it should work, but it doesn’t.

const getPhones = async () => {
  await fetch(url, requestOptions)
    .then((response) => response.text())
    .then((XMLdata) => {
      const parser = new XMLParser()
      const jObj = parser.parse(XMLdata)
      let data = jObj['soapenv:Envelope']['soapenv:Body']['ns:listPhoneResponse']['return']['phone']
      console.log(data)
      return data
    })
    .catch((error) => console.log('error', error))
}

the function returns JSON like this, I can see it in console.log(data):

[
  { name: 'SEP805E0C47A189', model: 'Third-party SIP Device (Basic)' },
  { name: 'SEPDCEB94CE9A65', model: 'Cisco 7821' },
  { name: 'TCT-442001', model: 'Cisco Dual Mode for iPhone' },
  { name: 'BOT-441015', model: 'Cisco Dual Mode for Android' },
  { name: 'SEP70708B219FC8', model: 'Cisco 8851' },
]

then everything is the same as everyone else export import express

export const phonesData = (req, res) => {
  res.status(200).json(getPhones)
}

router.get('/api/phones', phonesData)

but when I go to the page localhost:3000/api/phones I get a 200 response but the data that I see in the console is missing. I copied the data from the console.log into a constant, and tried to substitute the constant in export, the data appeared. The function getPhones is asynchronous, it waits for fetch to be executed, then the result is parsed by fast-xml-parser into JSON which is returned.
What am I doing wrong?

2

Answers


  1. Chosen as BEST ANSWER

    This is very strange, but I changed fetch to axios and everything worked for me.

    async function makeRequest() {
      try {
        const response = await axios.request(config)
        console.log(JSON.stringify(response.data))
        const parser = new XMLParser()
        const jObj = parser.parse(response.data)
        const data = jObj['soapenv:Envelope']['soapenv:Body']['ns:listPhoneResponse']['return']['phone']
        console.log(data)
        return data
      } catch (error) {
        console.log(error)
      }
    }
    
    

  2. getPhones is a function:

    const getPhones = async () => {
    

    Here you’re trying to return the function itself, rather than invoking it:

    export const phonesData = (req, res) => {
      res.status(200).json(getPhones)
    }
    

    You can invoke (call) a function by adding parentheses to it. Note also that getPhones is an async function, so you need to await its result:

    export const phonesData = async (req, res) => {
      res.status(200).json(await getPhones());
    }
    

    Or, if an async version of phonesData doesn’t suit your needs, you can follow the result with .then():

    export const phonesData = (req, res) => {
      getPhones().then(data => res.status(200).json(data));
    }
    

    Either way, you need to call the function in order for it to execute and return its result.


    Additionally, mixing await and .then() is a recipe for bugs:

    const getPhones = async () => {
      await fetch(url, requestOptions)
        .then((response) => response.text())
        .then((XMLdata) => {
          const parser = new XMLParser()
          const jObj = parser.parse(XMLdata)
          let data = jObj['soapenv:Envelope']['soapenv:Body']['ns:listPhoneResponse']['return']['phone']
          console.log(data)
          return data
        })
        .catch((error) => console.log('error', error))
    }
    

    If you want to use await syntax, use await syntax:

    const getPhones = async () => {
      try {
        const response = await fetch(url, requestOptions);
        const XMLdata = await response.text();
        const parser = new XMLParser();
        const jObj = parser.parse(XMLdata);
        let data = jObj['soapenv:Envelope']['soapenv:Body']['ns:listPhoneResponse']['return']['phone'];
        console.log(data);
        return data;
      } catch (error) {
        console.log('error', error);
      }
    }
    

    Alternatively, in lieu of await you can return the Promise chain. In which case the function doesn’t need to be async:

    const getPhones = () => {
      return fetch(url, requestOptions)
        .then((response) => response.text())
        .then((XMLdata) => {
          const parser = new XMLParser()
          const jObj = parser.parse(XMLdata)
          let data = jObj['soapenv:Envelope']['soapenv:Body']['ns:listPhoneResponse']['return']['phone']
          console.log(data)
          return data
        })
        .catch((error) => console.log('error', error))
    }
    

    In both cases the consuming code would treat it the same way, since both return a Promise which would resolve to data (or fail and log the error to the console).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search