-2

Code:

app.post('/new', urlencodedParser, function (req, res) {
  if (!req.body) return res.sendStatus(400);

  emitter.on('response', function (output) {
    res.status(200).json({ip: `${output}`, id: `${random_id}`});
  });
});

Problem:

The problem I'm having right now (I'm using express) is I can't make multiple requests to the app. Express returns the expected value the first time, and every time after that:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

The rest of the application is a collection of functions triggered by event emitters and listeners. Think of it as a string of emitters triggering listeners and executing 4 or 5 functions in succession, and, at the end, returning a value.

This works flawlessly for the first time, but never again. Note that requests are expected to come in from different machines, not a single machine.

I know res.end() will end the response but no combination of Express functions makes it work the second time. Is there a way to use emitters/listeners and Express responses?

Thanks in advance!

EDIT: more code

emitter.on('newRequest', persistentDisk);
emitter.on('newDisk', persistentDisk);
emitter.on('newDeployment', newDeployment);
emitter.on('newService', createService);
emitter.on('checkDeployment', checkDeployment);
emitter.on('returnIp', returnIp);

emitter.on('deleteRequest', deleteApp);

app.post('/new', urlencodedParser, function (req, res) {
  if (!req.body) return res.sendStatus(400);

  var random_id = randomize('a', 8);

  var user_id = req.body.user_id;
  var stripe_id = req.body.stripe_id;
  var app_name = req.body.app_name;
  var gpu_count = req.body.gpu_count;
  var cpu_count = req.body.cpu_count;
  var memory_count = req.body.memory_count;

  emitter.emit('newRequest', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count);
  emitter.on('response', function (output) {
    res.send({ip: `${output}`, id: `${random_id}`});
  });
    async function persistentDisk(random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count) {
      try {
            emitter.emit('newDeployment', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count);
            emitter.emit('newService', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count);
      } catch (err) {
        console.log(err);
        errors.report(err);
      }
    }

async function newDeployment(random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count) {
  try {
    var deployConfig = JSON.parse(`...`);

      emitter.emit('checkDeployment', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count);

  } catch (err) {
    console.log(err);
    errors.report(err);
  }
}

async function createService(random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count) {
  try {
    var exposeConfig = JSON.parse(`...`);

      emitter.emit('returnIp', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count)
  } catch (err) {
    console.log(err);
    errors.report(err);
  }
}

async function checkDeployment(random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count) {
  try {
  } catch (err) {
    console.log(err);
    errors.report(err);
  }
}

async function returnIp(random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count) {
  try {
    var service = JSON.parse(`{"ip":"127.0.0.1"}`)
    jq.run('.ip', service, { input: 'json' }).then((output) => {
      emitter.emit('response', output)
      if (output.toString() === "null") {
        setInterval(() => {
          console.log('value is null');
          emitter.emit('returnIp', random_id, user_id, stripe_id, app_name, gpu_count, cpu_count, memory_count)
        }, 15000);
        }
      });
  } catch (err) {
    console.log(err);
    errors.report(err);
  }
}

This produces a response (127.0.0.1, importantly) the first time.

Darwesh Singh
  • 31
  • 1
  • 7
  • You can't end a request twice, what are you trying to achieve? If you need to emit data to the client, you should use websockets. – Marcos Casagrande May 19 '18 at 14:19
  • The last function in a string of these functions has an if else statement that calls `emitter.emit('response', output)`. Edit: @MarcosCasagrande I'm trying to achieve an app that can respond to multiple requests from different machines with a computed value using emitters to trigger a sequence of functions. – Darwesh Singh May 19 '18 at 14:26
  • Show your code, if `emitter.emit` is not unique for the request, which is what is happening in your code, you will have that problem. – Marcos Casagrande May 19 '18 at 14:29
  • @MarcosCasagrande edited with more code. How would I make `emitter.emit` "unique for the request"? – Darwesh Singh May 19 '18 at 14:33
  • either you create an event emitter for each request which won't help you since that event is not tied to the request, or you use websockets, which is what you should be using, ending a request on an event that may never happen will lead to timeouts problem. – Marcos Casagrande May 19 '18 at 14:36

1 Answers1

0

Changing to:

app.post('/new', urlencodedParser, function (req, res) {
  if (!req.body) return res.sendStatus(400);

  emitter.once('response', function (output) {
    res.status(200).json({ip: `${output}`, id: `${random_id}`});
  });
});

(from emitter.on to emitter.once) resolves the issue.

Darwesh Singh
  • 31
  • 1
  • 7
  • it will "solve" the issue, this could lead to timeouts, or posting a different IP address, since a different request can emit the `response` event. It seems you're not interested on all the issues I explained to you. Your approach to the problem is wrong. – Marcos Casagrande May 19 '18 at 15:15