Alejandro
Alejandro

Reputation: 637

Nodejs respond after data has finished processing in request

I would like a response to differ depending on the finished request I recieve. I am sending a POST request and receive an xml file. The result is either a success or error. I use xml2json to convert the xml into a json object, then depending on the response I want to output json.

The problem is that I can't have a response inside a response. I also can't save the value of the callback for later usage (since its asynchronous).

I have thought about using Promises but I'm not sure. What should I do?

The order of operations should be

1) Send request

2) Get buffer response

3) Join Buffers. Process xml into JSON

4) Depending on the type of JSON entry, output either res.json('success') or res.json('error') if the xml responds with an error.

app.post('/api/submit', (req, res) => {

  ...

  const request = https.request(options, (res) => {
    let chunks = [];

    res.on("data", function(chunk) {
      chunks.push(chunk);
    });

    res.on("end", function(err) {
      if (err) throw err;
      let body = Buffer.concat(chunks);

      xmlConverter(body, function(err, result) {
        console.dir(result);
        if (result.entry) {
          console.log('✅  Success')
          //Respond with json here --> res.json('success')
        } else if (result.error) {
          console.log('There was an error processing your request');
          //or here if there was an error --> res.json('error')
        }
      });
    });
  });

  request.end()

Upvotes: 2

Views: 1033

Answers (3)

Mark
Mark

Reputation: 92440

You can respond inside the callback. The problem is that you have two variable, both named res, so one shadows the other. You just need to change one of the res variable names so your not shadowing it. For example, you can change:

const request = https.request(options, (http_res) // <--change argument name

Then later:

if (result.entry) {
    console.log('✅  Success')
    http_res.json('success') // <-- use the response object from request

The problem of not being able to save the result for later is a different problem, but easy to solve. The solution though really depends one what you are trying to do. If, for example, you want to further process the data, you can set up a function to call and pass the response data in. Something like:

function process_data(response){
    // use the response here
}

Then you can simply call it when you get the data:

if (result.entry) {
    console.log('✅  Success')
    http_res.json('success') // <-- use the response object from request
    process_data(result)

Of course maybe your use case is more complicated but without more details its hard to give a specific answer.

Upvotes: 1

ztech
ztech

Reputation: 560

What exactly is the issue? You are perfectly able to rename the argument of the callback function supplied to https.request(options, callbackFunction) -- it is not important what this variable is named.

app.post('/api/submit', (req, res) => {

  const request = https.request(options, (potato) => {
    let chunks = [];

    potato.on("data", function(chunk) {
      chunks.push(chunk);
    });

    potato.on("end", function(err) {
      if (err) throw err; // TODO res.status(500).json({}); ??
      let body = Buffer.concat(chunks);

      xmlConverter(body, function(err, result) {
        console.dir(result);
        if (result.entry) {
          console.log('✅  Success')
          res.status(200).json({});
        } else if (result.error) {
          console.log('There was an error processing your request');
          res.status(500).json({});
        }

        request.end()
      });
    });
  });
});

Upvotes: 0

David Vicente
David Vicente

Reputation: 3111

Don't use the same name for both res, because they are different variables. And simply use the out res variable to respond the request with the value you want. I think it would be something like this:

app.post('/

    api/submit', (req, res) => {

      ...

      const request = https.request(options, (resValue) => {
        let chunks = [];

        resValue.on("data", function(chunk) {
          chunks.push(chunk);
        });

        resValue.on("end", function(err) {
          if (err) throw err;
          let body = Buffer.concat(chunks);

          xmlConverter(body, function(err, result) {
            console.dir(result);
            if (result.entry) {
              console.log('✅  Success')
              res.json('success')
            } else if (result.error) {
              console.log('There was an error processing your request');
              res.json('error')
            }
          });
        });
      });

      request.end()

Upvotes: 1

Related Questions