4

I have below function in frontend, I have to make some api call here in this function. When i checked the called function via command prompt, the server api call returns 400. but the function in frontend fetch always returning 200 instead of error.

Thanks in advance. Please guide to how to correct response which is thrown from server call? Here is the frontend function.

function processFile() {
  var fileToLoad = document.getElementById("fileToLoad").files[0];
  var url;

  var fileReader = new FileReader();
  fileReader.onload = function(fileLoadedEvent) {
    var rows = fileLoadedEvent.target.result.split("\n");
    for (var i = 0; i < rows.length - 1; i++) {
      var cells = rows[i].split(",");
      //alert(cells);
      console.log("AgentteamID=" + cells[0] + " SkilltargetID=" + cells[1] + " flag=" + cells[2]);
      url = "/updateAgentTeam?agentTeamID=" + cells[0] + "&skillTargetID=" + cells[1] + "&flag=" + cells[2],
        //alert(url);
        console.log("URL=" + url);
      const response = fetch(url, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },

      }).then(response =>
        response.json().then(data => ({
          data: "success",
          status: response.status
        })).then(res => {
          var statusCode = JSON.stringify(res.status);
          //$('#Success_comment').html(JSON.stringify(res)+"---"+url;);
          //alert(url);
          document.getElementById("Success_comment").value += JSON.stringify(res) + "---" + url;
          console.log("final result " + JSON.stringify(res) + "---" + url);

        }))

    }
  }
  fileReader.readAsText(fileToLoad, "UTF-8");
}

Here is the Server side code. For now we are using only Flag A block

app.get("/updateAgentTeam", (req, res) => {
  var skillTargetID = req.query.skillTargetID;
  console.log("req.query.skillTargetID =" + req.query.skillTargetID);
  var agentTeamID = req.query.agentTeamID;
  var flag = req.query.flag;
  var finalurl = "http://198.18.133.11/unifiedconfig/config/agentteam/" + agentTeamID;
  var xml;
  //console.log("finalurl ="+finalurl);
  axios({
      url: finalurl,
      method: "get",
      auth: {
        username: "xxx",
        password: "yyy"
      },
    })
    .then(async(response) => {
      xml = response.data;
      //console.log("after calling xml is "+JSON.stringify(xml));
      res.send(response.data);

      if (flag === 'D') {
        agentremovedXML = removeAgentFromXML(xml, skillTargetID);
        //newxml=removeAgentFromXML(xml);
        //console.log("Final Agent remove XML "+JSON.stringify(agentremovedXML));
        postAgentToTeam(agentTeamID, agentremovedXML);
        //setSuccessJSON();
      } else if (flag === 'A') {
        AgentXML = await generateAgentXML(skillTargetID);
        console.log("Returned agent xml is " + JSON.stringify(AgentXML));
        console.log("xml where agent to be add " + JSON.stringify(xml));
        if (JSON.stringify(xml.agentCount) == 0) {
          AgentXML = {
            "agent": [AgentXML]
          };

          xml.agents = [AgentXML];
          console.log("xml with zero agents " + JSON.stringify(xml));
        } else {
          xml.agents[0].agent.push(AgentXML);
          console.log("Compare " + JSON.stringify(xml));
        }
        console.log("xml send to postAgentToTeam is " + xml);
        postAgentToTeam(agentTeamID, xml);
        //postAgentToTeam(agentTeamID,agentXML);
      }
    })
    .catch((err) => {
res.status(400);
      res.send(err.response.status);
      console.log(err);
      //setErrorJSON()
    });
});

async function postAgentToTeam(agentTeamID, xml) {
  var teamurl = "http://198.18.133.11/unifiedconfig/config/agentteam/" + agentTeamID;
  //console.log("final XML is "+JSON.stringify(xml));
  xml.agents = xml.agents[0].agent.map(agent => ({
    agent: agent
  }));
  var updatedJSONwithAgentTags = JSON.stringify(xml, null, " ");
  //console.log("newwwwwwwwwwwwwwwwwwwwww "+ updatedJSONwithAgentTags);
  //return;
  js2xml = json2xml(JSON.parse(JSON.stringify(xml)));
  json2 = "<agentTeam>" + js2xml + "</agentTeam>";
  //console.log("newwww converted XML "+json2);
  response = await axios({
      url: teamurl,
      method: "put",
      auth: {
        username: "administrator@dcloud.cisco.com",
        password: "C1sco12345"
      },
      data: json2,
      headers: {
        'Content-Type': 'application/xml; charset=utf-8'
      }
    })
    .then(response => {
      console.log("hellooo " + response.status);
    })
    .catch((err) => {
      console.log(err.response.data.apiError);
      console.log("error res is " + err.response.status);
    });
}
Ganesh Putta
  • 2,622
  • 2
  • 19
  • 26

2 Answers2

2

There's a few things wrong.

Inside your first .then(async(response) => {, you set the xml to response.data then right away call res.send(response.data) (200) which is the end of the execution order for Express. However, you go on to do a bunch of other things after the res.send (200) is sent. You should not do that.

You need to restructure your code. Starting from the top-down keeping in mind that all promises need to be returned and that res.send() is the end of the block. Throwing a 400 after this won't matter since Express already sent the response to the client.

You're also mutating theresponse output from Axios which is bad practice. Create a new one if you need to mutate it:

const newResponse = { ...response };

Additionally, this mixing of .then().catch() with an initial await is not how you should handles promises and would cause problems.

Don't write them like this:

response = await axios({}).then().catch().

Either do this:

axios({ // <--- no await, no let response =
  url: finalurl,
  method: "get",
  auth: {
    username: "xxx",
    password: "yyy"
  },
})
.then(async(response) => {
  // res.send, etc.
}).catch((e) => {
  // handle errors
});

Or use try / catch blocks like this:

try {
  const results = await axios({
    url: teamurl,
    method: "put",
    auth: {
      username: "administrator@dcloud.cisco.com",
      password: "C1sco12345"
    },
    data: json2,
    headers: {
      'Content-Type': 'application/xml; charset=utf-8'
    }
  }); // <--- the end.
  console.log({results});
} catch (e) {
  // handle errors
  console.log(e);
}
Wesley LeMahieu
  • 2,296
  • 1
  • 12
  • 8
1

Seems like a well known gotcha with chaining Promise.catch.

To fix it, do the following 2 changes:

  1. Remove ".catch(..." block from your postAgentToTeam function.
    Why? Because ".catch(..." by default eats up rejected promise and converts it into a successfully resolved promise. So remove the catch block from postAgentToTeam function. But if you do want to have a catch block (e.g. for debugging purpose), you can write "throw e" as the last line within that catch block. This will propogate the error in the chain.

  2. When calling postAgentToTeam function, await on it.
    Why? Because if you don't await, the returned promise is not going to get cascaded in enclosing promise's then/catch block. It's like we're getting a value in return but not using it. So just do: await postAgentToTeam(agentTeamID, xml)

To understand more about catch chaining and all the gotchas, there's a very nice documentation on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch

mg007
  • 2,888
  • 24
  • 29