I have a very simple route
router.get('/', async (req, res, next) => {
try {
const allEmployees = await employees.find({});
res.json(allEmployees);
} catch (error) {
next(error);
}
});
It works ok. But after I refactored it with catch
. it stopped working and threw UnhandledPromiseRejectionWarning:
router.get('/', async (req, res, next) => {
const allEmployees = await employees.find({}).catch(next)
res.json(allEmployees);
});
It seems like the next
is not called correctly in the second version. But Both should be equivalent in JavaScript. not sure why the second one is broken in Express.
CodePudding user response:
Both should be equivalent in JavaScript
No, they are not.
Promise.prototype.catch() returns a new promise that resolves with the return value of the callback. Since next()
returns void
, this code...
employees.find({}).catch(next)
returns a successful promise, resolving with undefined
. next()
will be called with the failure but there's nothing stopping the rest of your code from calling res.json(undefined)
.
If you want to use the Promise
prototype methods, the equivalent would be
router.get('/', (req, res, next) => {
employees.find({}).then(res.json).catch(next);
});
If you wanted to keep using async
/ await
and have the eventual promise fail, you'd need something like this
router.get("/", async (req, res, next) => {
const allEmployees = await employees
.find({})
.catch((err) => Promise.reject(next())); // rejected result
res.json(allEmployees);
});