Reputation: 5646
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.
Upvotes: 1
Views: 481
Reputation: 164970
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);
});
Upvotes: 2