5月29日 22:54

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

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