0

I have an express route, say:

app.use('/route', middleware, handler);

function middleware(req, res, next) {
    // do some async task
    if( success ) {
        // async task is successfully done. handler should be called
        next();
    } else {
        // error in async task, handler should not be called
        res.json({ message: 'fail'});
    }
}

handler(req, res, next) {
    res.json({ message: 'done'});
}

I want to do some task asynchronously and if that task is done successfully, then and then only the subsequent middlewares should be called.

The issue is before the asynchronous task is finished, the handler is called (as expected) and the response is ended. Thus, when the async task is finished and I try to call res.json() in middleware it gives me 'Can't set headers after they are sent' (as expceted)

So how do I make express wait in the middleware while it is doing async task such that once it is finished, only and then only the subsequent handlers should get called.

I have looked at (here)
But not much of help.

I have tried using req.pause() but that does not seem to work.

Anand Undavia
  • 3,493
  • 5
  • 19
  • 33
  • If you're using a promise to do your async call, pass your `next()` to the `then()` block and the `res.json({ message: 'done' })` to the `catch()`block https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise – t3__rry Apr 18 '18 at 15:13
  • 1
    That's why `next()` is a callback, instead of express simply waiting for the handler to return. You should call it when your async task is finished, not before. – Bergi Apr 18 '18 at 15:24
  • 1
    You need to show us your actual asynchronous code so we can advise more specifically. The crux of the issue is that you need to monitor when your asynchronous operation is done so you can then, and only then, continue the processing. That should be done with either a callback or a promise. How exactly to implement that depends upon the asynchronous code which you do not show us. – jfriend00 Apr 18 '18 at 15:26
  • @Bergi 's comment helped. I was actually passing `next` to some other function and that was getting called in the process. Fixed that. Now it is working. Thanks! – Anand Undavia Apr 18 '18 at 15:45

1 Answers1

3

You can use async on middleware and wait for your async execution to be completed using await on the execution. Your code should look like something.

And make sure to return a promise from your DoYourTask()

async function middleware(req, res, next) {
  var success = await DoYouTask();
  if( success ) {
    // async task is successfully done. handler should be called
    next();
 } else {
    // error in async task, handler should not be called
    res.json({ message: 'fail'});
 }
}
Muhammad Usman
  • 10,039
  • 22
  • 39
  • As many beginners fail to understand, it's worth pointing out that `await` only awaits an asynchronous operation if `DoYouTask()` returns a promise that is linked to the completion of the asynchronous operation. Without that, it doesn't do anything useful. Please, there's no requirement to use `async/await` here at all. Using `.then()` on the promise works just fine too. – jfriend00 Apr 18 '18 at 15:27
  • yeah you're right. you can do that with `.then()` and as OP has mentioned that he wants to perform `async task`. Moreover, I've mentioned that `DoYourTask` should return a promise. Did I mention something wrong here ? and yeah I am a learner – Muhammad Usman Apr 18 '18 at 15:32
  • @George Bailey I was doing the same thing in fact. The issue was I was passing the `next` in `DoYouTask` and it was getting called. ( Silly me :/ ) Thanks for the help! – Anand Undavia Apr 18 '18 at 15:44
  • Glad if I could help. Please consider upvoting and accepting the answer :) Thanks – Muhammad Usman Apr 18 '18 at 15:45