JAVASCRIPT
Optimizing API Calls with Request Batching
Improve application performance and reduce network overhead by combining multiple individual API requests into a single batched request to a custom backend endpoint.
// Client-side code to send batched requests
async function sendBatchedRequests(requests) {
// 'requests' is an array of objects, e.g.:
// [{ method: 'GET', path: '/users/1' }, { method: 'POST', path: '/products', body: { name: 'New Item' }}]
try {
const response = await fetch('/api/batch', { // Your custom batch endpoint on your backend
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requests),
});
if (!response.ok) {
throw new Error(`Batch request failed with status: ${response.status}`);
}
const data = await response.json();
console.log('Batched response:', data);
return data; // 'data' will likely be an array of responses for each original request
} catch (error) {
console.error('Error sending batched requests:', error);
throw error;
}
}
// --- Example Usage ---
// (async () => {
// const userRequests = [
// { method: 'GET', path: '/api/users/1' },
// { method: 'GET', path: '/api/users/2' },
// { method: 'POST', path: '/api/products', body: { name: 'Laptop', price: 1200 } }
// ];
// try {
// const batchResults = await sendBatchedRequests(userRequests);
// // batchResults might look like:
// // [
// // { status: 200, data: { id: 1, name: 'Alice' } },
// // { status: 200, data: { id: 2, name: 'Bob' } },
// // { status: 201, data: { productId: 'abc', name: 'Laptop' } }
// // ]
// console.log('Results of batched operations:', batchResults);
// } catch (error) {
// console.error('Failed to get batched results:', error);
// }
// })();
// --- Hypothetical Server-Side Endpoint (Node.js with Express) ---
/*
const express = require('express');
const axios = require('axios'); // Or fetch, or any HTTP client
const app = express();
app.use(express.json()); // For parsing application/json
app.post('/api/batch', async (req, res) => {
const requestsToProcess = req.body; // Array of { method, path, body }
if (!Array.isArray(requestsToProcess)) {
return res.status(400).json({ error: 'Request body must be an array of requests.' });
}
const results = [];
for (const request of requestsToProcess) {
try {
const { method, path, body } = request;
// IMPORTANT: Validate paths and methods to prevent SSRF or unauthorized access
// e.g., ensure path starts with '/api/' or is on an allow-list
if (!path.startsWith('/api/')) {
results.push({ status: 403, error: 'Unauthorized path' });
continue;
}
const targetUrl = `http://localhost:3000${path}`; // Or your actual internal API base URL
let apiResponse;
if (method === 'GET') {
apiResponse = await axios.get(targetUrl);
} else if (method === 'POST') {
apiResponse = await axios.post(targetUrl, body);
} else if (method === 'PUT') {
apiResponse = await axios.put(targetUrl, body);
} else if (method === 'DELETE') {
apiResponse = await axios.delete(targetUrl);
} else {
results.push({ status: 405, error: `Method ${method} not allowed.` });
continue;
}
results.push({ status: apiResponse.status, data: apiResponse.data });
} catch (error) {
console.error('Error processing batched request:', error.message);
results.push({ status: error.response?.status || 500, error: error.message });
}
}
res.json(results);
});
app.listen(3000, () => console.log('Batch server running on port 3000'));
*/
How it works: This snippet illustrates client-side implementation of API request batching. Instead of making multiple individual HTTP requests, the `sendBatchedRequests` function takes an array of desired operations (e.g., GET a user, POST a product) and sends them as a single POST request to a dedicated batch endpoint on your own backend. Your backend then processes each sub-request, gathers their individual responses, and returns them as a single consolidated JSON array to the client. This approach significantly reduces network overhead and latency, especially for applications that frequently need to fetch or update multiple pieces of data simultaneously. The commented-out server-side code provides a conceptual example of how the backend batch endpoint might handle these requests using Node.js and Express.