Caller Manager
The runtime engine that executes HTTP requests. Learn about global configuration, event handling, batch requests, and cache invalidation.
Overview
The IgniterCallerManager is the runtime engine behind every Caller instance. When you call .build() on your configuration, you receive a manager that handles all the heavy lifting: executing requests, managing interceptors, emitting events, and coordinating caching.
While the Request Builder focuses on configuring individual requests, the Manager provides global capabilities that affect all requests or operate outside the request lifecycle.
import { IgniterCallerManager } from '@igniter-js/caller';
// Your api instance IS a manager
const api = IgniterCaller.create()
.withBaseUrl('https://api.example.com')
.build();
// Manager-level operations
IgniterCallerManager.on('response', handleResponse);
IgniterCallerManager.invalidate('users:*');Instance vs Static Methods
The Manager exposes two types of methods:
| Type | Access | Purpose |
|---|---|---|
| Instance | api.get(), api.post() | Creating requests for this client |
| Static | IgniterCallerManager.on() | Global operations across all clients |
This design allows you to have multiple independent API clients while still coordinating global behaviors like event handling and cache invalidation.
// Two independent clients
const apiV1 = IgniterCaller.create().withBaseUrl('/api/v1').build();
const apiV2 = IgniterCaller.create().withBaseUrl('/api/v2').build();
// Global event listener applies to BOTH
IgniterCallerManager.on('response', (event) => {
console.log(`Response from ${event.url}: ${event.status}`);
});Creating Requests
The manager provides convenience methods for all HTTP verbs:
Batch Requests
Execute multiple requests in parallel with automatic error handling:
const results = await IgniterCallerManager.batch([
api.get('/users').execute(),
api.get('/posts').execute(),
api.get('/comments').execute(),
]);
// results is an array of { data, error, status } objects
const [users, posts, comments] = results;
if (users.error) {
console.log('Failed to fetch users');
} else {
console.log(`Fetched ${users.data.length} users`);
}Batch with Settlement
Batch requests use Promise.allSettled semantics—one failure doesn't abort the others:
const results = await IgniterCallerManager.batch([
api.get('/always-works').execute(),
api.get('/sometimes-fails').execute(),
api.get('/always-works-2').execute(),
]);
// Even if the second request fails, you get results from all three
results.forEach((result, index) => {
if (result.error) {
console.log(`Request ${index} failed: ${result.error.message}`);
} else {
console.log(`Request ${index} succeeded`);
}
});Typed Batch Results
For type safety with heterogeneous requests, use the generic form:
const [usersResult, postsResult] = await IgniterCallerManager.batch<
[User[], Post[]]
>([
api.get('/users').execute(),
api.get('/posts').execute(),
]);
// usersResult.data is User[] | null
// postsResult.data is Post[] | nullGlobal Events
Subscribe to events across all Caller instances for logging, analytics, or error tracking:
Event Handler Examples
// Error tracking
IgniterCallerManager.on('error', (event) => {
Sentry.captureException(event.error, {
tags: { url: event.url, method: event.method },
});
});
// Performance monitoring
IgniterCallerManager.on('response', (event) => {
if (event.duration > 1000) {
console.warn(`Slow request: ${event.url} took ${event.duration}ms`);
}
});
// Debug logging in development
if (process.env.NODE_ENV === 'development') {
IgniterCallerManager.on('request', (e) => console.log('→', e.method, e.url));
IgniterCallerManager.on('response', (e) => console.log('←', e.status, e.url));
}Cache Invalidation
Programmatically invalidate cached responses when data changes:
Cache Invalidation Patterns
// Pattern 1: Invalidate on mutation
async function createUser(data: CreateUserInput) {
const { data: user, error } = await api.post('/users')
.body(data)
.execute();
if (!error) {
IgniterCallerManager.invalidate('users:list');
}
return user;
}
// Pattern 2: Invalidate related data
async function updateUserProfile(userId: string, data: ProfileInput) {
await api.patch('/users/:id/profile')
.params({ id: userId })
.body(data)
.execute();
// Invalidate multiple related caches
IgniterCallerManager.invalidate(`users:${userId}`);
IgniterCallerManager.invalidate(`users:${userId}:profile`);
IgniterCallerManager.invalidate('users:list'); // List might show profile data
}
// Pattern 3: React hook integration
function useCreateUser() {
const queryClient = useQueryClient();
return async (data: CreateUserInput) => {
const { data: user } = await api.post('/users').body(data).execute();
// Invalidate Caller cache
IgniterCallerManager.invalidate('users:list');
// Invalidate React Query cache (if using both)
queryClient.invalidateQueries(['users']);
return user;
};
}Common Patterns
Best Practices
Manager Guidelines
- Use instance methods for requests —
api.get(),api.post(), etc. - Use static methods for global operations — events, invalidation
- Set up event handlers early — typically in your app's entry point
- Clean up subscriptions — especially in React useEffect or component unmount
- Use meaningful cache keys — makes invalidation patterns clearer
Next Steps
Request Builder
Master the fluent API for building type-safe HTTP requests. Learn how to configure URLs, bodies, headers, timeouts, caching, retries, and more with chainable methods.
HTTP Methods & Response Parsing
Deep dive into HTTP method handling, automatic content-type detection, and response parsing strategies. Learn how Caller processes different data formats.