乐闻世界logo
搜索文章和话题

How to implement concurrent requests and request cancellation in axios? Please provide code examples

3月7日 12:10

Axios Concurrent Requests

Axios provides axios.all() and axios.spread() methods to handle concurrent requests, and also supports using native Promise.all().

1. Using Promise.all() (Recommended)

javascript
// Send multiple requests simultaneously async function fetchMultipleData() { try { const [users, posts, comments] = await Promise.all([ axios.get('/api/users'), axios.get('/api/posts'), axios.get('/api/comments') ]); console.log('Users:', users.data); console.log('Posts:', posts.data); console.log('Comments:', comments.data); return { users: users.data, posts: posts.data, comments: comments.data }; } catch (error) { console.error('At least one request failed:', error); throw error; } }

2. Using axios.all() (Traditional Way)

javascript
axios.all([ axios.get('/api/users'), axios.get('/api/posts'), axios.get('/api/comments') ]) .then(axios.spread((users, posts, comments) => { // Execute when all requests succeed console.log('Users:', users.data); console.log('Posts:', posts.data); console.log('Comments:', comments.data); })) .catch(error => { // Execute when any request fails console.error('Request failed:', error); });

3. Concurrent Request Error Handling

javascript
async function fetchWithErrorHandling() { const requests = [ axios.get('/api/users'), axios.get('/api/posts'), axios.get('/api/comments') // Request that might fail ]; // Use Promise.allSettled to wait for all requests to complete const results = await Promise.allSettled(requests); results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`Request ${index} succeeded:`, result.value.data); } else { console.error(`Request ${index} failed:`, result.reason.message); } }); // Filter successful results const successfulResults = results .filter(result => result.status === 'fulfilled') .map(result => result.value.data); return successfulResults; }

4. Limiting Concurrency

javascript
// Use p-limit or custom implementation to limit concurrency async function fetchWithConcurrencyLimit(urls, limit = 3) { const results = []; const executing = []; for (const [index, url] of urls.entries()) { const promise = axios.get(url).then(res => ({ index, data: res.data })); results.push(promise); if (urls.length >= limit) { executing.push(promise); if (executing.length >= limit) { await Promise.race(executing); executing.splice( executing.findIndex(p => p === promise), 1 ); } } } return Promise.all(results); } // Usage const urls = ['/api/data/1', '/api/data/2', '/api/data/3', '/api/data/4']; fetchWithConcurrencyLimit(urls, 2);

Axios Request Cancellation

1. Using AbortController (Recommended, v0.22.0+)

javascript
// Create AbortController const controller = new AbortController(); // Pass signal when sending request axios.get('/api/data', { signal: controller.signal }) .then(response => { console.log(response.data); }) .catch(error => { if (axios.isCancel(error)) { console.log('Request cancelled:', error.message); } else { console.error('Request failed:', error); } }); // Cancel request controller.abort('User cancelled operation'); // Auto-cancel after 5 seconds setTimeout(() => { controller.abort('Request timeout'); }, 5000);

2. Using in React Components

javascript
import { useEffect } from 'react'; function UserList() { useEffect(() => { const controller = new AbortController(); const fetchUsers = async () => { try { const response = await axios.get('/api/users', { signal: controller.signal }); // Process data } catch (error) { if (axios.isCancel(error)) { console.log('Component unmounted, request cancelled'); } else { console.error('Failed to fetch users:', error); } } }; fetchUsers(); // Cancel request when component unmounts return () => { controller.abort('Component unmounted'); }; }, []); return <div>User List</div>; }

3. Using in Vue Components

javascript
<script setup> import { onMounted, onUnmounted } from 'vue'; let controller; onMounted(() => { controller = new AbortController(); axios.get('/api/data', { signal: controller.signal }) .then(response => { console.log(response.data); }) .catch(error => { if (axios.isCancel(error)) { console.log('Request cancelled'); } }); }); onUnmounted(() => { controller?.abort('Component unmounted'); }); </script>

4. Cancelling Multiple Requests

javascript
const controllers = new Map(); // Save controller when sending request function fetchWithCancel(key, url) { // Cancel previous request with same name if (controllers.has(key)) { controllers.get(key).abort('Duplicate request, cancel previous one'); } const controller = new AbortController(); controllers.set(key, controller); return axios.get(url, { signal: controller.signal }) .finally(() => { controllers.delete(key); }); } // Usage: Search box debounce scenario fetchWithCancel('search', '/api/search?q=keyword');

5. Auto-cancel on Timeout

javascript
async function fetchWithTimeout(url, timeout = 5000) { const controller = new AbortController(); const timeoutId = setTimeout(() => { controller.abort(`Request timeout (${timeout}ms)`); }, timeout); try { const response = await axios.get(url, { signal: controller.signal }); clearTimeout(timeoutId); return response.data; } catch (error) { clearTimeout(timeoutId); throw error; } }

6. Request Cancellation Utility Function

javascript
class RequestManager { constructor() { this.controllers = new Map(); } // Send request async request(key, config) { // Cancel previous request with same name this.cancel(key); const controller = new AbortController(); this.controllers.set(key, controller); try { const response = await axios({ ...config, signal: controller.signal }); return response; } finally { this.controllers.delete(key); } } // Cancel specified request cancel(key, message = 'Request cancelled') { if (this.controllers.has(key)) { this.controllers.get(key).abort(message); this.controllers.delete(key); } } // Cancel all requests cancelAll(message = 'All requests cancelled') { this.controllers.forEach(controller => { controller.abort(message); }); this.controllers.clear(); } } // Usage const requestManager = new RequestManager(); // Send request requestManager.request('userList', { method: 'GET', url: '/api/users' }); // Cancel specified request requestManager.cancel('userList'); // Cancel all requests (e.g., when page changes) requestManager.cancelAll();

Best Practices

  1. Cancel requests on component unmount: Avoid memory leaks and state update errors
  2. Cancel previous request on duplicate: Search box, form submission scenarios
  3. Set reasonable timeout: Prevent request hanging
  4. Handle cancellation errors correctly: Distinguish between cancellation and business errors
  5. Use AbortController: Modern browser standard API, good compatibility
标签:JavaScript前端Axios