Middleware Flow Control
middleware-flow is a JavaScript library providing enhanced control flow structures for Express-style middleware. It extends the basic sequential execution model by offering utilities for `series`, `parallel`, `parallelWait`, `each`, `or`, `and`, `if().then().else()`, `syncIf`, `asyncIf`, and `mwIf` operations. First published in 2015 and currently at version 0.8.0, it was developed primarily for CommonJS environments, common in older Node.js and Express applications, making it a useful tool for orchestrating complex middleware pipelines. Its key differentiator lies in its declarative API for non-sequential middleware execution, particularly for concurrent tasks or conditional branching, which are not natively provided by Express's core `app.use()` patterns. The project's development appears to be abandoned, with its last publish date being 11 years ago, and no further updates are expected.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use `require` in an ES Module context where it is not available.fixEnsure your Node.js environment is configured for CommonJS, or use a bundler/transpiler to handle the CommonJS module in an ESM project. You can also try dynamic `import()` if the module allows it (`import('middleware-flow').then(({ series }) => ...)`) but this library might not be designed for it. -
SyntaxError: Unexpected token 'if'
cause Attempting to destructure or declare a variable named `if`, which is a reserved JavaScript keyword.fixWhen destructuring, alias the 'if' export: `const { 'if': ifFlow } = require('middleware-flow');`. If importing the whole module, access it as a property: `const flow = require('middleware-flow'); app.use(flow.if(...));` -
Error: Can't set headers after they are sent to the client.
cause A middleware within a parallel, conditional, or iterative flow sent a response, but another middleware subsequently attempted to send headers or a response.fixEnsure that only one middleware is responsible for sending the final response or that subsequent middlewares correctly check `res.headersSent` before attempting to modify headers or send responses. Proper `next()` calls are crucial for controlling flow.
Warnings
- breaking The library is abandoned, with its last publish date being May 10, 2015. It is no longer actively maintained, meaning no further updates, bug fixes, or security patches will be released.
- gotcha The library exclusively uses CommonJS `require()` syntax and does not provide native ES Module (ESM) exports. Using it directly in an ESM-only Node.js project or browser environment will lead to errors without proper transpilation or bundling.
- gotcha The `if` utility uses a reserved JavaScript keyword. When destructuring, you must alias it (e.g., `const { 'if': ifFlow } = require('middleware-flow');`) or access it via the full module object (e.g., `const flow = require('middleware-flow'); flow.if(...)`).
- gotcha Error handling in `parallel` and `parallelWait` explicitly states that it 'returns the first error that occurred'. This means subsequent errors from other parallel middlewares will be ignored. Ensure your application logic accounts for this behavior.
Install
-
npm install middleware-flow -
yarn add middleware-flow -
pnpm add middleware-flow
Imports
- series
import { series } from 'middleware-flow';const { series } = require('middleware-flow'); - parallel
import parallel from 'middleware-flow/parallel';
const { parallel } = require('middleware-flow'); - if
const if = require('middleware-flow').if;const { 'if': ifFlow } = require('middleware-flow');
Quickstart
const express = require('express');
const { 'if': ifFlow, series } = require('middleware-flow');
const app = express();
// Dummy middlewares
const middlewareOne = (req, res, next) => {
console.log('Middleware One executed.');
next();
};
const middlewareTwo = (req, res, next) => {
console.log('Middleware Two executed.');
next();
};
const middlewareError = (req, res, next) => {
console.error('Error Middleware executed.');
res.status(500).send('An error occurred!');
};
// A synchronous function for ifFlow condition
function nameQueryExists (req, res) {
return !!req.query.name;
}
app.use('/conditional',
ifFlow(nameQueryExists) // Checks if req.query.name exists
.then(middlewareOne, middlewareTwo) // If true, run these sequentially
.else(middlewareError) // If false, run the error middleware
);
app.use('/', series(middlewareOne, middlewareTwo, (req, res) => {
res.send('Hello from middleware-flow! Try /conditional?name=test or /conditional');
}));
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000');
});