Execute a fetch request with middleware applied
This method applies all registered middleware (both v1 and v2) and executes the fetch request. Middleware are executed in priority order (v2) and registration order (v1 backward compatibility).
The URL or Request object to fetch
Optional init: RequestInitOptional RequestInit configuration
Promise that resolves to the Response
const api = createFej();
const response = await api.fej('https://api.example.com/users');
const data = await response.json();
const response = await api.fej('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John' }),
});
Set global request initialization options (deprecated)
This method sets global configuration that applies to all requests made with the singleton. It is deprecated in favor of instance-based configuration.
Request initialization options to set globally
This method is deprecated and will be removed in a future version. Use instance-based configuration instead:
const api = createFej({ baseURL: "...", headers: {...} });
Add synchronous middleware (deprecated)
This method adds a synchronous middleware function using the legacy v1 API.
It is deprecated in favor of the unified use() method which supports both
sync and async middleware with better control and naming.
Legacy synchronous middleware function
This method is deprecated and will be removed in a future version.
Use the unified use() method instead:
api.use("middleware-name", async (ctx, next) => {
// Modify request
ctx.request.init.headers = new Headers(ctx.request.init.headers);
ctx.request.init.headers.set('X-Custom', 'value');
await next();
});
Add asynchronous middleware (deprecated)
This method adds an asynchronous middleware function using the legacy v1 API.
It is deprecated in favor of the unified use() method which handles both
sync and async middleware automatically.
Legacy asynchronous middleware function
This method is deprecated and will be removed in a future version.
Use the unified use() method instead (handles both sync and async automatically):
api.use("middleware-name", async (ctx, next) => {
// Async operations supported
const token = await getAuthToken();
ctx.request.init.headers = new Headers(ctx.request.init.headers);
ctx.request.init.headers.set('Authorization', `Bearer ${token}`);
await next();
});
Add named middleware with optional priority
Register a middleware function that will be executed in the request/response pipeline. Middleware are executed in descending priority order (higher priority runs first). Uses Koa-style onion model where middleware can execute code before and after calling next().
Unique identifier for the middleware (will replace existing with same name)
Middleware function (Koa-style with ctx and next)
Optional priority (default: 0, higher = earlier execution)
The unique ID of the middleware (for internal tracking)
const api = createFej();
api.use('custom-header', async (ctx, next) => {
ctx.request.init.headers = new Headers(ctx.request.init.headers);
ctx.request.init.headers.set('X-Custom', 'value');
await next();
});
api.use('logger', async (ctx, next) => {
const start = Date.now();
console.log(`→ ${ctx.request.url}`);
await next(); // Execute request and downstream middleware
const duration = Date.now() - start;
console.log(`← ${ctx.request.url} (${duration}ms)`);
});
// Auth runs first (priority: 100)
api.use('auth', authMiddleware, 100);
// Logger runs second (priority: 0, default)
api.use('logger', loggerMiddleware);
Remove middleware by name
Removes a previously registered middleware from the pipeline.
The name of the middleware to remove
true if middleware was removed, false if not found
api.use('temp', tempMiddleware);
const removed = api.removeMiddleware('temp'); // true
const removed2 = api.removeMiddleware('nonexistent'); // false
Enable or disable middleware without removing it
Allows temporarily disabling middleware without removing it from the pipeline. Useful for debugging or conditional middleware execution.
The name of the middleware
Whether to enable (true) or disable (false)
true if middleware was found, false otherwise
api.use('debug', debugMiddleware);
api.toggleMiddleware('debug', false); // Disable debug logging
// ... do something ...
api.toggleMiddleware('debug', true); // Re-enable debug logging
Get the list of all registered middleware names
Returns middleware names in the order they will execute (sorted by priority).
Array of middleware names in priority order (highest priority first)
api.use('auth', authMiddleware, 100);
api.use('logger', loggerMiddleware, 0);
api.use('retry', retryMiddleware, 50);
const names = api.getMiddlewareNames(); // ['auth', 'retry', 'logger']
Add an error transformation function
Error transforms allow you to customize error handling globally. Transforms are executed in registration order for all errors.
Function to transform errors
const api = createFej();
api.addErrorTransform(async (error, ctx) => {
// Add context to all errors
const enhancedError = new Error(`[${ctx.request.url}] ${error.message}`);
enhancedError.stack = error.stack;
return enhancedError;
});
Set default retry configuration
Configures the default retry behavior for the instance. This affects middleware that use retry logic.
Partial retry configuration
const api = createFej();
api.setDefaultRetry({
attempts: 5,
delay: 2000,
backoff: 'exponential',
});
Create a new AbortController for request cancellation
Creates an AbortController instance for cancelling requests. The controller is tracked internally and can be aborted by ID or tags.
Optional id: stringOptional custom identifier for the controller (generated if not provided)
Optional tags: string[]Optional tags for grouping requests (e.g., ['user-profile', 'high-priority'])
Object containing the AbortController and the request ID
const { controller, requestId } = api.createAbortController();
const response = await api.fej('https://api.example.com/users', {
signal: controller.signal,
});
const { controller } = api.createAbortController(undefined, ['dashboard', 'user-data']);
const response = await api.fej('/api/user', { signal: controller.signal });
// Later: cancel all dashboard requests
api.abortRequestsByTag('dashboard');
Abort a request by ID
Cancels a specific request using its ID. The request ID is returned when creating an AbortController.
The ID of the request to abort
Optional options: CancellationOptionsOptional cancellation options (e.g., custom reason)
true if request was aborted, false if not found
const { controller, requestId } = api.createAbortController();
const fetchPromise = api.fej('/api/data', { signal: controller.signal });
// Cancel after 5 seconds
setTimeout(() => {
const aborted = api.abortRequest(requestId, { reason: 'Timeout' });
console.log(aborted); // true
}, 5000);
Abort all requests with a specific tag
Cancels all requests that were tagged with the specified tag. Useful for cancelling groups of related requests (e.g., all dashboard requests).
The tag to match
Optional options: CancellationOptionsOptional cancellation options (e.g., custom reason)
Number of requests aborted
// Tag requests with 'dashboard'
const { controller: c1 } = api.createAbortController(undefined, ['dashboard']);
const { controller: c2 } = api.createAbortController(undefined, ['dashboard']);
const p1 = api.fej('/api/users', { signal: c1.signal });
const p2 = api.fej('/api/stats', { signal: c2.signal });
// Cancel all dashboard requests
const count = api.abortRequestsByTag('dashboard'); // returns 2
Abort all pending requests
Cancels all currently pending requests tracked by this Fej instance. Use with caution as this will cancel ALL requests.
Optional options: CancellationOptionsOptional cancellation options (e.g., custom reason)
// User navigates away - cancel all pending requests
window.addEventListener('beforeunload', () => {
api.abortAllRequests({ reason: 'Navigation' });
});
Get all requests with a specific tag
Returns request IDs for all requests tagged with the specified tag.
The tag to match
Array of request IDs with this tag
const dashboardRequests = api.getRequestsByTag('dashboard');
console.log(`Dashboard has ${dashboardRequests.length} pending requests`);
Check if a request is pending
Checks whether a specific request ID is still pending.
The request ID
true if pending, false otherwise
const { requestId } = api.createAbortController();
const pending = api.isRequestPending(requestId); // true
api.abortRequest(requestId);
const stillPending = api.isRequestPending(requestId); // false
Fej - Fetch with middleware support
The main class that provides middleware capabilities for the Fetch API. Supports both legacy v1 singleton pattern and new v2 instance-based approach.
Example