Express Promise Router
raw JSON →express-promise-router is a lightweight wrapper for Express 4's native `Router` that significantly simplifies the handling of asynchronous operations by allowing middleware and route handlers to return Promises. When a Promise is returned, its resolution or rejection is automatically managed, eliminating the need for explicit `next()` calls on successful resolution or `.catch(next)` for rejections. This package is currently on version 4.1.1 and receives regular updates, typically in the form of patch and minor releases, with major versions occurring when significant changes like Node.js version support are introduced. Its primary differentiator is its seamless integration with existing Express applications as a drop-in replacement for `express.Router()`, promoting cleaner, more readable code, especially when leveraging `async/await` syntax. Unlike solutions that patch the `app` object, this library focuses specifically on router instances, allowing for granular control over promise-aware routing.
Common errors
error Cannot read property '0' of undefined ↓
router.get('/', (req, res) => { ... });. error My promise resolves, but the client doesn't receive any response. ↓
res.send(), res.json(), res.end(), or similar Express response methods within your promise chain or async function body to send data back to the client. Warnings
breaking Version 4.0.0 of `express-promise-router` dropped support for older Node.js versions (v4, v6, v8). Applications targeting these environments must remain on `express-promise-router` v3.x or update their Node.js runtime. ↓
breaking Version 2.0.0 removed support for Node.js versions older than 4 and switched from Bluebird to native Promises. If you rely on Bluebird-specific features or target ancient Node.js runtimes, you must stick to `express-promise-router` v1.x. ↓
gotcha Values returned or resolved by promise-based route handlers are NOT automatically sent as a response to the client. This design choice prevents accidental leakage of sensitive data or internal state. ↓
gotcha `express-promise-router` currently only promisifies `Router` instances, not the main Express `app` object. Attempting to use promise-returning middleware directly on `app` will not have the same automatic error handling. ↓
Install
npm install express-promise-router yarn add express-promise-router pnpm add express-promise-router Imports
- Router wrong
import { Router } from 'express-promise-router';correctimport Router from 'express-promise-router'; - Router (CommonJS)
const Router = require('express-promise-router'); - Router (TypeScript) wrong
import * as Router from 'express-promise-router';correctimport Router from 'express-promise-router';
Quickstart
import express from 'express';
import PromiseRouter from 'express-promise-router';
const app = express();
const router = PromiseRouter();
// Mount the promise-aware router onto the express app
app.use(router);
// Example 1: Async/await route handler
router.get('/users/:id', async (req, res) => {
try {
// Simulate fetching user data from a database
const user = await Promise.resolve({ id: req.params.id, name: 'John Doe', permission: 'USER' });
if (user.permission !== 'ADMIN') {
throw new Error('Access Denied: You must be an admin.');
}
res.status(200).json({ message: `Welcome, ${user.name}!` });
} catch (error) {
// Errors thrown from async functions are automatically caught and passed to next()
// For this example, we'll manually send a response for clarity.
// In a real app, an error handler middleware would catch this.
throw error; // This will trigger the router's error handler
}
});
// Example 2: Promise resolution to call next() or next('route')
router.get('/next-example', (req, res) => {
// Equivalent to calling next()
return Promise.resolve('next');
});
router.get('/next-example', (req, res) => {
res.send('Reached the next handler!');
});
// Global error handler for the router (will catch errors from promise rejections)
router.use((err, req, res, next) => {
console.error('Caught an error:', err.message);
res.status(err.statusCode || 500).send(err.message || 'Internal Server Error');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});