-1

I want to combine middlewares in express to make them parallel, as opposed to sequential if you put the in app.use(path, /* middlewares *,/ callback).

I write the following function:

function makeParallelMiddleware(args) {
  let makePromises = (req, res) => args.map((func) => {
    return new Promise((resolve, reject) => {
      console.log('In promise: ' + func.name);
      func(req, res, resolve);
    })
  });
  return (req, res, next) => Promise.all(makePromises(req, res)).then(next())
}

But this does not seem to work properly. I test with the following two middlewares:

function middlewareA(req, res, next) {
  req.A = 1;
  console.log('I am in A');
  setTimeout(() => {
    console.log('I am in A delay');
    if (req.C) {
      req.C = 'BA'
    } else {
      req.C = 'A'
    }
    next()
  }, 1000)
}

function middlewareB(req, res, next) {
  req.B = 1;
  if (req.C) {
    req.C = 'AB'
  } else {
    req.C = 'B'
  }
  next()
}

app.get('/parallel', makeParallelMiddleware([middlewareA, middlewareB]) ,(req, res) => {
  res.send(req.C);
});

When I access /parallel, I can only get "B" instead of "BA".

How can it be possible that the promise is resolved before req.C is set? How do I correct this to get the desired result?

Colliot
  • 1,522
  • 3
  • 16
  • 29
  • 1
    `then(next())` should be `then(next)`. – Felix Kling Mar 17 '16 at 21:25
  • If you want to go down the promise route, you should make your middlewares return promises. If for some reason you still need callbacks, you can't just pass `resolve` around, as failing works differently with promises. See [here](http://stackoverflow.com/q/22519784/1048572) how properly get a promise from node-style callbacks. – Bergi Mar 17 '16 at 22:19

1 Answers1

1

Change this:

return (req, res, next) => Promise.all(makePromises(req, res)).then(next())
//                                                   remove parens here ^^ 

to this:

return (req, res, next) => Promise.all(makePromises(req, res)).then(function(results) {
    next();
});

You were calling next() immediately rather than passing a function reference that can be called later by the .then() method. Also, next() probably doesn't like an array to be passed to it which is what .then() would pass in your case, so better to just wrap in a custom function and just call plain next().


And, you also need some error handling if either of your promises rejects which they could if they throw an exception.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I'm pretty sure that `next` doesn't like to be called with an array as the first argument. Try `.then(next.bind(null, null), next)` instead. – Bergi Mar 17 '16 at 22:19
  • @Bergi - Yeah, I wondered what would happen in that case. I've edited. – jfriend00 Mar 17 '16 at 22:20