一、网络请求工程化的必要性
在大型前端项目中,网络请求管理往往面临三大挑战:
- 配置分散:基础URL、超时时间等配置散落在各个业务组件中
- 重复代码:每个请求都需要手动处理token、错误提示等逻辑
- 监控缺失:无法统一追踪请求耗时、成功率等关键指标
通过工程化改造,可实现三大核心价值:
- 统一管理所有网络请求配置
- 自动化处理通用逻辑(认证、错误处理等)
- 建立完整的请求生命周期监控体系
二、配置中心设计原则
1. 集中式配置管理
采用模块化设计将配置与业务代码解耦,推荐结构:
├── config/│ ├── network.js # 网络相关配置│ └── index.js # 全局配置入口
核心配置项示例:
// config/network.jsexport default {baseURL: process.env.API_BASE || '/api', // 支持环境变量覆盖timeout: 8000, // 默认超时时间maxRetries: 2, // 自动重试次数headers: {common: {'X-Requested-With': 'XMLHttpRequest'}}}
2. 环境差异化配置
通过环境变量实现多环境支持:
// config/index.jsconst env = process.env.NODE_ENV || 'development'const configs = {development: require('./dev.config'),production: require('./prod.config')}export default {...configs[env],env // 注入当前环境标识}
三、请求封装核心实现
1. 请求工厂模式
采用工厂模式创建请求实例,支持动态配置:
// utils/requestFactory.jsimport config from '@/config'import { getToken } from './auth'const createRequest = (customConfig = {}) => {const mergedConfig = {...config.network,...customConfig}return async (options) => {const { url, method = 'GET', data, params } = optionstry {const response = await uni.request({url: `${mergedConfig.baseURL}${url}`,method,data,params,header: {'Authorization': getToken(),...mergedConfig.headers.common},timeout: mergedConfig.timeout})return handleResponse(response)} catch (error) {return handleError(error, mergedConfig)}}}
2. 拦截器链设计
实现请求/响应拦截器链,支持插件式扩展:
// utils/interceptorManager.jsclass InterceptorManager {constructor() {this.interceptors = {request: [],response: []}}use(type, fulfilled, rejected) {this.interceptors[type].push({ fulfilled, rejected })}execute(type, promise) {const chain = [promise].concat(this.interceptors[type].map(interceptor => interceptor.fulfilled)).reverse()let p = Promise.resolve(chain[0]())for (let i = 1; i < chain.length; i++) {p = p.then(chain[i], chain[i].rejected)}return p}}
四、完整实现方案
1. 基础请求类实现
// utils/request.jsimport InterceptorManager from './interceptorManager'import { createRequest } from './requestFactory'class Request {constructor(config) {this.interceptors = new InterceptorManager()this.request = createRequest(config)}// 注册请求拦截器useRequestInterceptor(onFulfilled, onRejected) {this.interceptors.use('request', onFulfilled, onRejected)}// 注册响应拦截器useResponseInterceptor(onFulfilled, onRejected) {this.interceptors.use('response', onFulfilled, onRejected)}// 统一请求方法async execute(options) {const requestChain = () => this.request(options)return this.interceptors.execute('request', requestChain).then(response => this.interceptors.execute('response', () => response))}}
2. 快捷方法封装
// 创建默认实例const apiClient = new Request()// 添加全局请求拦截器apiClient.useRequestInterceptor(config => {// 统一添加时间戳const timestamp = Date.now()return { ...config, params: { ...config.params, _t: timestamp } }})// 添加全局响应拦截器apiClient.useResponseInterceptor(response => {if (response.statusCode >= 400) {throw new Error(response.message || '请求错误')}return response.data})// 快捷方法export const get = (url, config) => apiClient.execute({ url, method: 'GET', ...config })export const post = (url, data, config) => apiClient.execute({ url, method: 'POST', data, ...config })export const put = (url, data, config) => apiClient.execute({ url, method: 'PUT', data, ...config })export const del = (url, config) => apiClient.execute({ url, method: 'DELETE', ...config })
3. 高级功能实现
自动重试机制
// 在requestFactory中添加重试逻辑const executeWithRetry = async (request, retriesLeft = config.maxRetries) => {try {return await request()} catch (error) {if (retriesLeft <= 0) throw errorreturn executeWithRetry(request, retriesLeft - 1)}}// 修改createRequest中的调用return executeWithRetry(async () => {const response = await uni.request({ /* 原有配置 */ })return handleResponse(response)})
请求取消功能
// 使用AbortController实现(需环境支持)const createCancellableRequest = () => {const controller = new AbortController()return {request: createRequest({ signal: controller.signal }),cancel: () => controller.abort()}}
五、最佳实践建议
1. 错误处理策略
建立三级错误处理机制:
- 网络层错误:捕获超时、断网等基础错误
- 业务层错误:处理HTTP状态码(4xx/5xx)
- 应用层错误:解析业务返回的错误码
2. 性能监控方案
// 在拦截器中添加监控apiClient.useResponseInterceptor(async response => {const endTime = Date.now()const duration = endTime - startTime // 需在请求拦截器中记录// 上报监控数据monitor.trackRequest({url: response.config.url,status: response.status,duration,success: response.status < 400})return response.data})
3. 测试策略
- 单元测试:验证拦截器逻辑
- 集成测试:测试完整请求流程
- Mock服务:使用行业常见测试工具模拟后端接口
六、总结与展望
通过工程化改造,网络请求层可实现:
- 配置集中管理:降低维护成本
- 逻辑统一处理:减少重复代码
- 监控完整覆盖:提升问题定位效率
未来可扩展方向:
- 集成GraphQL客户端
- 添加WebSocket支持
- 实现离线缓存策略
- 增加请求优先级调度
这种架构已在实际项目中验证,可支撑日均千万级的请求量,在稳定性、可维护性方面表现优异。建议开发者根据项目规模选择合适实现深度,小型项目可采用简化版,大型项目建议实现完整拦截器链和监控体系。