Middleware system for intercepting and modifying API calls before execution and after completion. Supports both global interceptors that apply to all API calls and method-specific interceptors for targeted API modification.
Add interceptors to modify API behavior globally or for specific methods.
/**
* Add global or method-specific interceptors for API calls
* @param method - API method name for specific interceptor, or interceptor config for global
* @param option - Interceptor configuration with hook functions (optional for global)
*/
function addInterceptor(method: string | InterceptorConfig, option?: InterceptorConfig): void;Usage Examples:
import uni from "@dcloudio/uni-mp-weixin";
// Add global interceptor for all API calls
uni.addInterceptor({
invoke(args) {
console.log('API called with args:', args);
// Modify request arguments globally
return args;
},
success(res) {
console.log('API succeeded:', res);
return res;
},
fail(err) {
console.error('API failed:', err);
return err;
},
complete(res) {
console.log('API completed:', res);
return res;
}
});
// Add interceptor for specific API method
uni.addInterceptor('request', {
invoke(args) {
// Add authentication headers
args.header = args.header || {};
args.header.Authorization = 'Bearer ' + getToken();
// Add request timestamp
args.data = args.data || {};
args.data.timestamp = Date.now();
console.log('Request intercepted:', args);
return args;
},
success(res) {
console.log('Request successful:', res);
// Process response data
if (res.data && res.data.code === 200) {
res.data = res.data.result;
}
return res;
},
fail(err) {
console.error('Request failed:', err);
// Handle authentication errors
if (err.statusCode === 401) {
uni.navigateTo({ url: '/pages/login/login' });
}
return err;
}
});
// Add interceptor for showToast
uni.addInterceptor('showToast', {
invoke(args) {
// Standardize toast duration
args.duration = args.duration || 2000;
// Add default icon if not specified
if (!args.icon) {
args.icon = 'none';
}
return args;
}
});Remove specific interceptors or all interceptors for a method.
/**
* Remove interceptors for API calls
* @param method - API method name for specific removal, or interceptor config for global removal
* @param option - Specific interceptor configuration to remove (optional)
*/
function removeInterceptor(method: string | InterceptorConfig, option?: InterceptorConfig): void;Usage Examples:
import uni from "@dcloudio/uni-mp-weixin";
// Remove specific interceptor function
const requestInterceptor = {
invoke(args) {
// Add auth header
args.header = args.header || {};
args.header.Authorization = 'Bearer ' + token;
return args;
}
};
uni.addInterceptor('request', requestInterceptor);
// Later, remove the specific interceptor
uni.removeInterceptor('request', requestInterceptor);
// Remove all interceptors for a specific method
uni.removeInterceptor('request');
// Remove global interceptor
const globalInterceptor = {
invoke(args) {
console.log('Global invoke');
return args;
}
};
uni.addInterceptor(globalInterceptor);
// Remove global interceptor
uni.removeInterceptor(globalInterceptor);Interceptors support multiple hook points in the API call lifecycle.
interface InterceptorConfig {
/** Called before API execution with request arguments */
invoke?: (args: any) => any;
/** Called when API succeeds with success result */
success?: (result: any) => any;
/** Called when API fails with error information */
fail?: (error: any) => any;
/** Called when API completes (success or fail) with result */
complete?: (result: any) => any;
/** Called to modify the final return value */
returnValue?: (value: any) => any;
}Automatically add authentication tokens to API requests:
uni.addInterceptor('request', {
invoke(args) {
// Get token from storage
const token = uni.getStorageSync('authToken');
if (token) {
args.header = args.header || {};
args.header.Authorization = `Bearer ${token}`;
}
return args;
},
fail(error) {
// Handle auth errors
if (error.statusCode === 401) {
// Token expired, redirect to login
uni.removeStorageSync('authToken');
uni.reLaunch({ url: '/pages/login/login' });
}
return error;
}
});Global error handling and user feedback:
uni.addInterceptor({
fail(error) {
// Log all API errors
console.error('API Error:', error);
// Show user-friendly error messages
const errorMessage = getErrorMessage(error);
uni.showToast({
title: errorMessage,
icon: 'none',
duration: 3000
});
return error;
}
});
function getErrorMessage(error) {
const errorMap = {
400: 'Invalid request',
401: 'Authentication required',
403: 'Access denied',
404: 'Resource not found',
500: 'Server error'
};
return errorMap[error.statusCode] || 'Network error';
}Standardize API response format:
uni.addInterceptor('request', {
success(res) {
// Standardize response structure
if (res.data && typeof res.data === 'object') {
// Extract data from wrapper
if (res.data.code === 200 && res.data.data) {
res.data = res.data.data;
} else if (res.data.success && res.data.result) {
res.data = res.data.result;
}
}
return res;
}
});Automatically manage loading states:
let loadingCount = 0;
uni.addInterceptor('request', {
invoke(args) {
// Show loading if not already shown
if (loadingCount === 0) {
uni.showLoading({ title: 'Loading...' });
}
loadingCount++;
return args;
},
complete(res) {
// Hide loading when all requests complete
loadingCount--;
if (loadingCount === 0) {
uni.hideLoading();
}
return res;
}
});Automatically retry failed requests:
uni.addInterceptor('request', {
fail(error) {
// Only retry on network errors
if (error.errno && error.errno !== 0) {
const retryCount = error._retryCount || 0;
const maxRetries = 3;
if (retryCount < maxRetries) {
console.log(`Retrying request (${retryCount + 1}/${maxRetries})`);
// Add retry count to track attempts
const originalArgs = error._originalArgs;
if (originalArgs) {
originalArgs._retryCount = retryCount + 1;
// Retry after delay
setTimeout(() => {
uni.request(originalArgs);
}, 1000 * (retryCount + 1));
}
}
}
return error;
}
});Validate request data before sending:
uni.addInterceptor('request', {
invoke(args) {
// Validate required fields
if (args.method === 'POST' && args.url.includes('/api/users')) {
const data = args.data || {};
const requiredFields = ['name', 'email'];
for (const field of requiredFields) {
if (!data[field]) {
throw new Error(`Missing required field: ${field}`);
}
}
// Validate email format
if (data.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
throw new Error('Invalid email format');
}
}
return args;
}
});The package includes several built-in interceptors:
Converts callback-style APIs to Promise-based returns:
// Built-in promise interceptor
const promiseInterceptor = {
returnValue(res) {
if (!isPromise(res)) {
return res;
}
return res.then(res => {
return res[1]; // Extract success result
}).catch(res => {
return res[0]; // Extract error result
});
}
};
// Access built-in interceptors
uni.interceptors.promiseInterceptor;// Main interceptor configuration interface
interface InterceptorConfig {
/** Called before API execution with request arguments */
invoke?: (args: any) => any;
/** Called when API succeeds with success result */
success?: (result: any) => any;
/** Called when API fails with error information */
fail?: (error: any) => any;
/** Called when API completes (success or fail) with result */
complete?: (result: any) => any;
/** Called to modify the final return value */
returnValue?: (value: any) => any;
}
// Built-in interceptors object
interface Interceptors {
promiseInterceptor: InterceptorConfig;
}