Express Promise Router

raw JSON →
4.1.1 verified Thu Apr 23 auth: no javascript

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.

error Cannot read property '0' of undefined
cause You are calling a router method (e.g., `router.get`, `router.post`) without providing a path argument.
fix
Always specify a path as the first argument to router methods, for example: router.get('/', (req, res) => { ... });.
error My promise resolves, but the client doesn't receive any response.
cause The library is designed not to automatically send the resolved value of a promise as a response to prevent accidental data leakage.
fix
Ensure you explicitly call 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.
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.
fix Upgrade Node.js to a supported version (>=10 for v4.x) or pin `express-promise-router` dependency to `<4.0.0`.
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.
fix Ensure your Node.js version is >=4 and update any Bluebird-specific Promise logic to use native Promises or pin `express-promise-router` dependency to `<2.0.0`.
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.
fix Explicitly call a response method like `res.send()`, `res.json()`, or `res.end()` within your promise chain or `async` function to send data back to the client.
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.
fix Always mount an `express-promise-router` instance onto your `app` (e.g., `app.use(promiseRouter);`) and define your promise-based routes and middleware on that router instance.
npm install express-promise-router
yarn add express-promise-router
pnpm add express-promise-router

This quickstart demonstrates how to initialize and use `express-promise-router` with an Express application, including basic `async/await` route handlers, explicit promise resolution for `next()` calls, and a global error handling middleware that captures promise rejections.

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}`);
});