D. Kaiser
D. Kaiser

Reputation: 179

Call express middlewares next() inside a promise chain

I am trying to build a parameter middleware that loads a requested object and appends it to the request object, so that I don't have to write the same code over and over again. I am using Sequelize as an ORM to access a MySQL Database, which is Promise based (bluebird). The code is as follows:

router.param('id', function (req, res, next, id) {
  return models.Object.findById(id)
    .then((object) => {
      //Check if the requested object was found
      if (object) {
        //Append the request object to the request object
        //for further usage in upcoming route handlers
        req.object = object
        return next()
      } else {
        //Throw an error, so that it can be caught
        //by the catch block of the promise chain
        let err = new Error('Object not found.')
        err.status = 404
        throw err
      }
    })
    //Catch any error and forward it to the
    //next express error handler
    .catch((err) => { return next(err) })
})

As you can see I am checking whether the requested object exists and if it exists, I append it to the request object of express. If not I am throwing an error. When I am running this code I get the warning: Warning: a promise was created in a handler at /*path goes here*/ but was not returned from it. At this point I don't really know how to get rid of that error.

Edit:

I tried the Solution of Hosar but unfortunately the warning still occurs. Here is the exact code I am using:

router.param('aId', function (req, res, next, aId) {
  models.Authorization.findById(aId)
    .then((authorization) => {
      if (authorization) {
        req.authorization = authorization
        next()
      } else {
        let err = new Error('Not Found')
        err.status = 404
        next(err)
      }
    })
    .catch((err) => { return next(err) })
})

The error occurs on the line where I want to call next() without any parameters. The complete warning is: (node:5504) Warning: a promise was created in a handler at C:\Users\dkaiser \repos\lead\lead_backend\routes\auth.js:10:16 but was not returned from it

Upvotes: 3

Views: 2482

Answers (2)

Ogie
Ogie

Reputation: 1334

You can extract data directly from a resolved Promise using an async middleware function from Node v7.6

router.param('id', async function (req, res, next, id) {
  const object = await models.Object.findById(id);
  if (object) {
    req.object = object;
    next();
  } else {
    let err = new Error('Object not found.')
    err.status = 404
    next(err);
  }
 });

Upvotes: 0

Hosar
Hosar

Reputation: 5292

The issue is you are returning a promise. Just avoid the first return you have.
Try:

router.param('id', function (req, res, next, id) {
  models.Object.findById(id)
    .then((object) => {
      //Check if the requested object was found
      if (object) {
        //Append the request object to the request object
        //for further usage in upcoming route handlers
        req.object = object
        next()
      } else {
        //Throw an error, so that it can be caught
        //by the catch block of the promise chain
        let err = new Error('Object not found.')
        err.status = 404
        next(err);
      }
    })
    //Catch any error and forward it to the
    //next express error handler
    .catch((err) => { next(err) })
})

Upvotes: 3

Related Questions