// Encapsulation of an API request library based on Axiosimport axios from'axios';import qs from'qs'; // Import qs module for serializing POST data// Set default API base URL based on environmentswitch (process.env.NODE_ENV) {case'production': axios.defaults.baseURL ='http://api.zhufengpeixun.cn';break;case'test': axios.defaults.baseURL ='http://192.168.20.12:8080';break;default: axios.defaults.baseURL ='http://127.0.0.1:3000';}// Set request timeoutaxios.defaults.timeout =10000;// Allow CORS credentialsaxios.defaults.withCredentials =true;// Set POST request headers: Inform server of data formataxios.defaults.headers['Content-Type'] ='application/x-www-form-urlencoded';axios.defaults.transformRequest=data=> qs.stringify(data);// Request interceptoraxios.interceptors.request.use(config=> {removePending(config); // Cancel any identical pending requestsaddPending(config);// JWT token validation: Retrieve token from local storage and include in headersconst token = localStorage.getItem('token');if (token) { config.headers.Authorization = token; }return config; },error=> {returnPromise.reject(error); });// Response interceptoraxios.defaults.validateStatus=status=> {// Define successful HTTP status codesreturn/^(2|3)\d{2}$/.test(status);};axios.interceptors.response.use(response=> {removePending(response.config);// Return only the response data (some companies may further customize based on server response codes)return response.data; },error=> {if (error.response) {switch (error.response.status) {case400: error.message ='Bad Request (400)';break;case401: // Unauthorized, typically not logged in error.message ='Unauthorized, please login (401)';break;case403: // Server understood request but refused (often due to expired token) error.message ='Forbidden (403)'; localStorage.removeItem('token');// Redirect to login pagebreak; }returnPromise.reject(error.response); } else {// Handle network disconnectionif (!window.navigator.onLine) {// Redirect to offline page if network is disconnectedreturn; }returnPromise.reject(error); } });// Request cancellationconst pendingMap =newMap();functiongetPendingKey(config) {const { url, method, params, data } = config;let requestBody = data || {};if (typeof requestBody ==='string') { requestBody =JSON.parse(requestBody); // Parse JSON string to object }return [url, method, JSON.stringify(params), JSON.stringify(requestBody)].join('&');}functionaddPending(config) {const pendingKey =getPendingKey(config); config.cancelToken = config.cancelToken ||new axios.CancelToken(cancel=> {if (!pendingMap.has(pendingKey)) { pendingMap.set(pendingKey, cancel); } });}functionremovePending(config) {const pendingKey =getPendingKey(config);if (pendingMap.has(pendingKey)) {const cancel = pendingMap.get(pendingKey);cancel(pendingKey); pendingMap.delete(pendingKey); }}functionclearPending() {for (const [url, cancel] of pendingMap) {cancel(url); } pendingMap.clear();}exportdefault axios;
login.js
// API module for loginimport axios from'./http';functionlogin() {return axios.post('/login', { xxx:'xxx', });}exportdefault { login };
api.js
// Centralized entry point for API requestsimport login from'./login';exportdefault { login,};
Encapsulating an API Request Library with Fetch
// Encapsulation of an API request library based on Fetchimport qs from'qs';/* * Differentiate API base URL based on environment */let baseURL ='';const baseURLArr = [ { type:'development', url:'http://127.0.0.1:9000', }, { type:'test', url:'http://192.168.20.15:9000', }, { type:'production', url:'http://api.zhufengpeixun.cn', },];baseURLArr.forEach(item=> {if (process.env.NODE_ENV=== item.type) { baseURL = item.url; }});exportdefaultfunctionrequest(url, options= {}) { url = baseURL + url;/* * Handle GET series requests */if (!options.method) { options.method ='GET'; }if (options.hasOwnProperty('params')) {if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.method)) {const ask = url.includes('?') ?'&':'?'; url +=`${ask}${qs.stringify(options.params)}`; }delete options.params; }/* * Merge configuration options */ options = Object.assign( {// Allow cross-origin credentials credentials:'include', // 'same-origin' for same-origin only, 'omit' to reject all// Set request headers headers: {}, }, options ); options.headers.Accept ='application/json';/* * Token validation */const token = localStorage.getItem('token');if (token) { options.headers.Authorization = token; }/* * Handle POST requests */if (/^(POST|PUT)$/i.test(options.method)) {if (!options.type) { options.type ='urlencoded'; }if (options.type ==='urlencoded') { options.headers['Content-Type'] ='application/x-www-form-urlencoded'; options.body = qs.stringify(options.body); }if (options.type ==='json') { options.headers['Content-Type'] ='application/json'; options.body =JSON.stringify(options.body); } }returnfetch(url, options) .then(response=> {// Handle non-200 status codesif (!/^(2|3)\d{2}$/.test(response.status)) {switch (response.status) {case401: // Unauthorized, typically not logged inbreak;case403: // Server understood but refused (often due to expired token) localStorage.removeItem('token');// Redirect to login pagebreak;case404: // Resource not foundbreak; }returnPromise.reject(response); }return response.json(); }) .catch(error=> {// Handle network disconnectionif (!window.navigator.onLine) {// Redirect to offline page if network is disconnectedreturn; }returnPromise.reject(error); });}
Code Analysis
Axios Encapsulation: Provides a robust HTTP client with request/response interceptors, token validation, request cancellation, and environment-based base URLs. The http.js module centralizes configuration, login.js defines specific API endpoints, and api.js serves as the unified entry point.
Fetch Encapsulation: A lightweight alternative using the native Fetch API, supporting environment-based base URLs, token validation, and request type handling (GET/POST). It simplifies configuration but lacks advanced features like request cancellation compared to Axios.
Key Features: Both implementations handle CORS credentials, error handling (e.g., 401, 403), and network disconnection scenarios, ensuring reliable API interactions.