I'm struggling to grasp the concept of writing middleware in Express that uses async/await without leaving a floating Promise after execution. Despite reading numerous blogs and StackOverflow posts, it appears that there is a common pattern for utilizing async/await middleware:
const asyncHandler = fn => (req, res, next) =>
Promise
.resolve(fn(req, res, next))
.catch(next)
app.use(asyncHandler(async (req, res, next) => {
req.user = await User.findUser(req.body.id);
next();
}));
I understand that this approach eliminates the need for try..catch logic in all async route-handlers, and ensures the resolution of Promises returned by (async (req, res, next) => {}) function. However, my concern lies with returning a Promise from the asyncHandler's Promise.resolve() call:
Promise
.resolve(fn(req, res, next))
.catch(next)
We never call then() on this returned Promise. Is this pattern used because we don't depend on any return values from middleware functions? Is it acceptable to simply return Promises without calling then() to access their value since middleware in Express doesn't typically return meaningful results?
While async/await simplifies managing asynchronous code and handling return values, the top-level async in Express middleware still results in a Promise, which is then resolved using Promise.resolve(), but still ends up as a Promise...
Although third-party solutions exist for this issue and alternative frameworks like Koa can be used, I am focused on understanding the proper way to handle this in Express as I am new to backend development with Node and want to master the fundamentals.
My current approach involves using async/await only outside of middleware functions, and then chaining then() in actual middleware calls to ensure proper handling, such as:
app.use((req, res, next) => {
User.findUser(req.body.id)
.then(user => {
req.user = user;
next();
})
.catch(next)
});
This method works fine for me, but I keep encountering the asyncWrapper code frequently. Am I overcomplicating things here?