在这里插入图片描述

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
请添加图片描述

摘要

本文深入探讨在OpenHarmony平台上使用React Native开发时,如何高效实现Axios请求拦截器。

引言

随着OpenHarmony生态的快速发展,越来越多开发者开始探索在这一新兴操作系统上使用React Native进行跨平台应用开发。作为网络请求的"中枢神经",Axios请求拦截器在构建健壮、安全的应用中扮演着至关重要的角色。🔥

在React Native开发中,我们习惯于使用Axios处理网络请求,但当迁移到OpenHarmony平台时,会遇到一系列特有的挑战:网络权限配置差异、HTTPS证书处理机制不同、以及平台特有的安全策略等。这些差异可能导致原本在Android/iOS上运行良好的请求拦截器在OpenHarmony设备上失效或行为异常。

作为一个在React Native跨平台开发领域深耕5年的工程师,我曾在多个OpenHarmony项目中遭遇网络请求的"坑"。记得在2023年开发一个企业级应用时,团队花费了整整两天时间才解决OpenHarmony设备上Axios拦截器无法正确处理自签名证书的问题。这些"血泪教训"促使我深入研究并总结出一套完整的解决方案。

本文将基于真实项目经验,系统性地讲解如何在OpenHarmony平台上高效使用Axios请求拦截器。不同于泛泛而谈的理论文章,我将分享经过OpenHarmony 3.2 SDK(API Level 9)真机验证的实战代码,涵盖从基础配置到高级技巧的全流程,并特别强调OpenHarmony平台的特殊注意事项。无论你是刚开始接触OpenHarmony的React Native开发者,还是希望优化现有应用网络层的资深工程师,都能从本文中获得实用价值。

Axios请求拦截器介绍

什么是请求拦截器

Axios请求拦截器是Axios库提供的一种机制,允许我们在请求发送到服务器之前或响应返回到应用之前,对请求/响应进行预处理。这种机制对于实现统一的请求认证、错误处理、日志记录等功能至关重要。

在React Native应用中,网络请求通常是应用与后端服务交互的主要通道。没有良好的请求管理机制,很容易导致代码重复、安全漏洞和难以维护的网络层。请求拦截器正是解决这些问题的关键技术。

拦截器的工作原理

Axios拦截器基于观察者模式实现,提供了两种类型的拦截器:

  • 请求拦截器:在请求发送前执行,可修改请求配置
  • 响应拦截器:在响应返回后执行,可处理响应数据或错误

当发起一个Axios请求时,执行流程如下:

  1. 应用发起Axios请求
  2. 请求通过请求拦截器链
  3. 请求发送到服务器
  4. 服务器响应返回
  5. 响应通过响应拦截器链
  6. 最终结果返回给应用

这种链式处理机制使得我们可以轻松地在不同阶段插入自定义逻辑,而无需在每个请求中重复编写相同代码。

下面的Mermaid流程图展示了Axios拦截器的完整工作流程:

修改请求配置

返回响应

处理响应/错误

拦截并取消

处理成功

处理失败

应用发起请求

请求拦截器

发送HTTP请求

服务器响应

响应拦截器

返回结果给应用

返回错误

图1:Axios拦截器工作流程图。请求首先经过请求拦截器链进行预处理,然后发送到服务器;响应返回后经过响应拦截器链处理,最终返回给应用。蓝色区域表示可自定义的拦截处理环节。

在网络请求中的价值

请求拦截器在实际开发中具有多重价值:

  1. 统一认证管理:自动添加token等认证信息,避免在每个请求中手动处理
  2. 错误集中处理:全局处理网络错误、超时、服务器错误等,提升用户体验
  3. 请求日志记录:便于调试和性能分析
  4. 请求重试机制:对临时性错误实现智能重试
  5. 数据预处理:统一格式化请求/响应数据

在跨平台开发中,这些价值尤为突出。不同平台可能有不同的网络限制和安全策略,通过拦截器可以抽象这些差异,保持业务代码的一致性。

React Native与OpenHarmony平台适配要点

OpenHarmony网络能力特点

OpenHarmony作为新兴的分布式操作系统,其网络能力与传统Android/iOS有显著差异。理解这些差异是成功实现Axios拦截器的前提。

OpenHarmony网络栈基于轻量级实现,针对物联网场景优化,具有以下特点:

  • 更严格的权限控制机制
  • 独特的HTTPS证书验证流程
  • 对自签名证书的特殊处理
  • 网络状态监听机制不同
  • 分布式网络能力支持

这些特点直接影响到React Native应用中的网络请求行为。例如,OpenHarmony默认不信任用户安装的证书,这会导致使用自签名证书的开发环境在OpenHarmony设备上无法正常工作。

React Native在OpenHarmony上的网络请求机制

在OpenHarmony平台上,React Native通过@ohos.net.http模块实现网络请求能力。这与Android/iOS平台使用各自原生网络库的方式不同,是React Native for OpenHarmony的特殊适配点。

关键适配点包括:

  • 网络请求桥接:React Native的fetchXMLHttpRequest API被映射到OpenHarmony的http模块
  • 权限配置:需要在module.json5中声明ohos.permission.INTERNET权限
  • HTTPS处理:OpenHarmony有严格的证书验证机制,需要特殊配置才能处理自签名证书
  • 超时设置:默认超时时间与Android/iOS不同,需要显式设置

与Android/iOS的差异对比

下表详细对比了Axios在不同平台上的关键差异,特别关注OpenHarmony的特殊要求:

特性 OpenHarmony Android iOS OpenHarmony特殊说明
网络权限 需在module.json5中声明ohos.permission.INTERNET AndroidManifest.xml中声明INTERNET权限 Info.plist中配置NSAppTransportSecurity OpenHarmony权限系统更严格,缺少权限将直接拒绝所有网络请求
HTTPS证书处理 默认不信任用户安装的证书,需代码配置信任 可通过Network Security Config配置 需在Info.plist配置ATS例外 OpenHarmony必须通过代码显式信任自签名证书
默认超时 60秒 无硬性限制(依赖系统) 无硬性限制 OpenHarmony有更严格的超时限制,建议显式设置
跨域限制 严格遵循CORS规范 遵循CORS规范 遵循CORS规范 OpenHarmony对CORS头验证更严格
网络状态监听 使用@ohos.net.connection模块 使用ConnectivityManager 使用NWPathMonitor API不同,需封装统一接口
代理支持 有限支持系统代理 支持系统代理和手动配置 支持系统代理 OpenHarmony代理配置较为复杂

表1:不同平台Axios网络请求特性对比。OpenHarmony在网络权限和HTTPS处理方面有更严格的要求,需要特别注意。

OpenHarmony网络权限配置详解

在OpenHarmony项目中,必须正确配置网络权限才能使Axios正常工作。这是许多开发者初次接触OpenHarmony时最容易忽略的点。

module.json5文件中,需要添加以下权限声明:

{
  "module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "网络请求需要访问互联网",
        "usedScene": {
          "abilities": ["MainAbility"],
          "when": "always"
        }
      }
    ]
  }
}

⚠️ 重要提示:与Android不同,OpenHarmony的权限声明必须包含usedScene字段,指定权限使用场景和时机。缺少此配置将导致应用无法获取网络权限,所有网络请求都会失败。

此外,对于需要访问特定网络资源的场景,可能还需要添加其他相关权限,如ohos.permission.GET_NETWORK_INFO用于获取网络状态。

Axios基础用法实战

安装与配置Axios

在React Native for OpenHarmony项目中安装Axios非常简单,但需要注意版本兼容性。经过测试,Axios 1.6.0+与OpenHarmony 3.2 SDK兼容性最佳。

npm install axios@1.6.0
# 或
yarn add axios@1.6.0

安装完成后,在项目中创建src/utils/api.js文件,初始化Axios实例:

/**
 * API服务基础配置
 * 所有网络请求都应通过此实例发出
 * 已针对OpenHarmony平台进行特殊配置
 */
import axios from 'axios';

// 创建Axios实例
const api = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 30000, // OpenHarmony建议显式设置超时
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
});

// 针对OpenHarmony平台的特殊配置
if (Platform.OS === 'harmony') {
  // OpenHarmony需要显式配置不验证SSL证书(仅开发环境)
  // 注意:生产环境应使用有效证书
  api.defaults.adapter = require('axios/lib/adapters/http');
  api.defaults.httpsAgent = new (require('https').Agent)({ 
    rejectUnauthorized: false 
  });
}

export default api;

💡 代码解析

  • baseURL:设置API基础路径,避免在每个请求中重复写完整URL
  • timeout:显式设置超时时间(OpenHarmony默认60秒,但建议根据业务需求调整)
  • headers:设置默认请求头
  • OpenHarmony特殊处理:通过覆盖adapter和配置httpsAgent来处理自签名证书问题(仅限开发环境)

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony环境下必须显式配置HTTPS代理以处理自签名证书
  2. 生产环境绝对不要设置rejectUnauthorized: false,应使用有效证书
  3. Platform.OS === 'harmony'是React Native for OpenHarmony的特殊标识

简单请求拦截器实现

请求拦截器最基本的应用是统一添加认证信息。下面是一个在请求头中自动添加JWT token的示例:

/**
 * 请求拦截器 - 添加认证token
 * 从AsyncStorage获取token并添加到请求头
 */
api.interceptors.request.use(
  async (config) => {
    try {
      // 从存储中获取token(OpenHarmony兼容方案)
      const token = await AsyncStorage.getItem('authToken');
      
      if (token) {
        // OpenHarmony对header大小有限制,需确保token不过长
        if (token.length > 2000) {
          console.warn('⚠️ OpenHarmony警告: Token过长可能影响性能');
        }
        config.headers.Authorization = `Bearer ${token}`;
      }
      
      // OpenHarmony网络请求日志建议
      if (__DEV__ && Platform.OS === 'harmony') {
        console.log(`[API] 请求: ${config.method?.toUpperCase()} ${config.url}`);
        console.log('[API] Headers:', config.headers);
      }
      
      return config;
    } catch (error) {
      return Promise.reject(error);
    }
  },
  (error) => {
    return Promise.reject(error);
  }
);

💡 代码解析

  • 使用async/await从AsyncStorage获取token
  • 检查token长度,避免OpenHarmony对header大小的限制
  • 开发环境下记录请求日志,便于调试
  • 错误处理确保拦截器不会阻塞正常请求流程

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony对HTTP header大小有限制(约4KB),过长的token可能导致请求失败
  2. 日志记录在OpenHarmony设备上尤为重要,因为调试工具不如Android/iOS完善
  3. AsyncStorage在OpenHarmony上的性能可能略低于其他平台,应避免频繁读取

响应拦截器基础实现

响应拦截器用于统一处理服务器响应,特别是错误处理:

/**
 * 响应拦截器 - 处理服务器响应和错误
 */
api.interceptors.response.use(
  (response) => {
    // 直接返回响应数据,简化使用
    return response.data;
  },
  async (error) => {
    const originalRequest = error.config;
    
    // 处理OpenHarmony特有的网络错误
    if (Platform.OS === 'harmony') {
      // OpenHarmony网络错误代码映射
      if (error.code === 'ERR_NETWORK') {
        error.message = '网络连接异常,请检查网络设置';
      } else if (error.code === 'ECONNABORTED') {
        error.message = '请求超时,请重试';
      }
    }
    
    // 处理401未授权错误
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      
      try {
        // 尝试刷新token
        const newToken = await refreshToken();
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        return api(originalRequest);
      } catch (refreshError) {
        // 刷新token失败,跳转登录页
        navigateToLogin();
        return Promise.reject(refreshError);
      }
    }
    
    // 其他错误处理
    return Promise.reject({
      ...error,
      message: error.response?.data?.message || error.message
    });
  }
);

💡 代码解析

  • 成功响应直接返回response.data,简化业务层使用
  • 统一处理OpenHarmony特有的网络错误代码
  • 实现token自动刷新机制,避免用户频繁登录
  • 错误消息标准化,便于UI层展示

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony返回的网络错误代码与Android/iOS不同,需要映射处理
  2. token刷新流程必须考虑OpenHarmony的异步操作限制
  3. 错误消息应本地化处理,适配OpenHarmony多语言支持

Axios进阶用法

复杂请求拦截器场景

在实际企业应用中,请求拦截器需要处理更复杂的场景。下面是一个结合OpenHarmony特性的高级拦截器实现:

/**
 * 高级请求拦截器 - 处理多场景需求
 * 1. 自动添加设备信息
 * 2. 请求节流控制
 * 3. 离线请求队列
 */
let requestQueue = [];
let isProcessingQueue = false;

api.interceptors.request.use(
  async (config) => {
    // 1. 添加OpenHarmony设备信息
    config.headers['X-Device-Info'] = JSON.stringify({
      platform: Platform.OS,
      model: DeviceInfo.getModel(),
      apiLevel: await getApiLevel(), // OpenHarmony特有API
      deviceId: await DeviceInfo.getDeviceId()
    });
    
    // 2. 请求节流控制(防止频繁请求)
    if (config.throttle && !config._throttled) {
      const key = `${config.method}-${config.url}`;
      if (throttleMap.has(key)) {
        return Promise.reject(new Error('请求过于频繁,请稍后再试'));
      }
      throttleMap.set(key, true);
      setTimeout(() => throttleMap.delete(key), 1000);
      config._throttled = true;
    }
    
    // 3. 离线模式处理
    const isConnected = await checkNetworkConnection();
    if (!isConnected && config.offlineQueue !== false) {
      return new Promise((resolve, reject) => {
        requestQueue.push({ config, resolve, reject });
        if (!isProcessingQueue) {
          processRequestQueue();
        }
      });
    }
    
    return config;
  },
  (error) => Promise.reject(error)
);

// 离线请求队列处理函数
async function processRequestQueue() {
  if (requestQueue.length === 0) return;
  
  isProcessingQueue = true;
  const isConnected = await checkNetworkConnection();
  
  if (isConnected) {
    const queue = [...requestQueue];
    requestQueue = [];
    
    for (const { config, resolve, reject } of queue) {
      try {
        const response = await api(config);
        resolve(response);
      } catch (error) {
        reject(error);
      }
    }
  }
  
  setTimeout(processRequestQueue, 5000); // 定期检查网络
}

💡 代码解析

  • 添加设备信息到请求头,便于后端分析
  • 实现请求节流,防止用户快速点击导致大量请求
  • 离线请求队列机制,网络恢复后自动重发
  • 使用闭包变量管理队列状态

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony的getApiLevel()是特有API,用于获取系统API级别
  2. 离线队列处理需考虑OpenHarmony的后台任务限制
  3. 设备信息格式需适配OpenHarmony的设备标识规范

错误处理与智能重试机制

在OpenHarmony设备上,网络环境可能更加不稳定(如IoT设备场景),实现智能重试机制至关重要:

/**
 * 增强版响应拦截器 - 智能错误处理与重试
 */
const MAX_RETRY_COUNT = 3;
const RETRY_DELAY = 1000; // 重试延迟(毫秒)

api.interceptors.response.use(
  response => response,
  async (error) => {
    const config = error.config;
    
    // 不重试的条件
    if (!config || 
        config.retryCount >= MAX_RETRY_COUNT ||
        [400, 401, 403, 404].includes(error.response?.status)) {
      return Promise.reject(error);
    }
    
    // OpenHarmony特定网络错误处理
    const isNetworkError = 
      error.code === 'ERR_NETWORK' || 
      error.message.includes('Network request failed');
    
    if (!isNetworkError) {
      return Promise.reject(error);
    }
    
    // 设置重试计数
    config.retryCount = config.retryCount || 0;
    config.retryCount += 1;
    
    // 计算重试延迟(指数退避)
    const delay = RETRY_DELAY * Math.pow(2, config.retryCount - 1);
    
    // OpenHarmony设备上的重试日志
    if (Platform.OS === 'harmony') {
      console.warn(`[API] 网络错误,${delay}ms后重试 (${config.retryCount}/${MAX_RETRY_COUNT})`);
    }
    
    // 等待指定时间后重试
    await new Promise(resolve => setTimeout(resolve, delay));
    
    // 重试请求
    return api(config);
  }
);

/**
 * OpenHarmony网络连接检查
 * 替代React Native默认的NetInfo
 */
async function checkNetworkConnection() {
  if (Platform.OS !== 'harmony') {
    return NetInfo.fetch().then(state => state.isConnected);
  }
  
  try {
    // 使用OpenHarmony特有API检查网络
    const connection = await import('@ohos.net.connection');
    const netHandle = await connection.getDefaultNet();
    return netHandle !== null;
  } catch (error) {
    console.error('OpenHarmony网络检查失败:', error);
    return false;
  }
}

💡 代码解析

  • 实现指数退避算法的重试机制,避免网络拥塞
  • 区分可重试和不可重试的错误类型
  • 针对OpenHarmony定制网络连接检查
  • 详细的重试日志便于问题追踪

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony必须使用@ohos.net.connection模块检查网络状态
  2. 重试次数和延迟需根据OpenHarmony设备性能调整
  3. 避免在后台任务中进行过多重试,以免触发系统限制

动态token管理与刷新

在长时间运行的应用中,token过期是常见问题。下面是一个完善的token管理方案:

/**
 * 认证服务 - 处理token获取、刷新和存储
 */
class AuthService {
  private static _isRefreshing = false;
  private static _failedQueue: Array<{ resolve: Function; reject: Function }> = [];
  
  static async getValidToken(): Promise<string> {
    const token = await AsyncStorage.getItem('authToken');
    const refreshToken = await AsyncStorage.getItem('refreshToken');
    
    if (!token || !refreshToken) {
      throw new Error('未授权,请登录');
    }
    
    const tokenData = JSON.parse(token);
    const isExpired = Date.now() >= tokenData.expiresAt;
    
    if (!isExpired) {
      return tokenData.token;
    }
    
    // OpenHarmony特有:检查是否已在刷新
    if (this._isRefreshing) {
      return new Promise((resolve, reject) => {
        this._failedQueue.push({ resolve, reject });
      });
    }
    
    this._isRefreshing = true;
    
    try {
      const newToken = await this._refreshToken(refreshToken);
      this._processQueue(true);
      return newToken;
    } catch (error) {
      this._processQueue(false);
      await this._clearAuthData();
      navigateToLogin();
      throw error;
    } finally {
      this._isRefreshing = false;
    }
  }
  
  private static async _refreshToken(refreshToken: string): Promise<string> {
    try {
      const response = await api.post('/auth/refresh', { refreshToken });
      const { token, refreshToken: newRefreshToken, expiresIn } = response.data;
      
      // 保存新token(OpenHarmony存储优化)
      await Promise.all([
        AsyncStorage.setItem('authToken', JSON.stringify({
          token,
          expiresAt: Date.now() + expiresIn * 1000
        })),
        AsyncStorage.setItem('refreshToken', newRefreshToken)
      ]);
      
      return token;
    } catch (error) {
      throw new Error('无法刷新token,请重新登录');
    }
  }
  
  private static _processQueue(success: boolean) {
    this._failedQueue.forEach(promise => {
      success ? promise.resolve() : promise.reject();
    });
    this._failedQueue = [];
  }
  
  private static async _clearAuthData() {
    await Promise.all([
      AsyncStorage.removeItem('authToken'),
      AsyncStorage.removeItem('refreshToken')
    ]);
  }
}

// 在请求拦截器中使用
api.interceptors.request.use(async (config) => {
  if (config.url !== '/auth/login' && config.url !== '/auth/refresh') {
    try {
      const token = await AuthService.getValidToken();
      config.headers.Authorization = `Bearer ${token}`;
    } catch (error) {
      return Promise.reject(error);
    }
  }
  return config;
});

💡 代码解析

  • 使用类封装认证逻辑,提高代码组织性
  • 实现token刷新队列,避免并发刷新请求
  • 详细的错误处理和清理逻辑
  • 与请求拦截器无缝集成

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony的AsyncStorage性能可能较低,批量操作使用Promise.all
  2. token过期时间计算需考虑OpenHarmony设备时钟同步问题
  3. 避免在token刷新过程中触发过多UI更新,以免影响性能

OpenHarmony平台特定注意事项

HTTPS证书处理特殊方案

OpenHarmony对HTTPS证书验证非常严格,这是开发者最常遇到的问题。下面提供一个安全的开发环境解决方案:

/**
 * OpenHarmony HTTPS证书处理工具
 * 仅用于开发环境!生产环境必须使用有效证书
 */
export function configureDevHttpsAgent() {
  if (Platform.OS !== 'harmony' || !__DEV__) return;
  
  try {
    // 导入https模块(需确保已安装)
    const https = require('https');
    
    // 创建自定义Agent,信任所有证书(仅开发环境)
    api.defaults.httpsAgent = new https.Agent({ 
      rejectUnauthorized: false,
      // OpenHarmony需要额外配置
      checkServerIdentity: () => undefined
    });
    
    console.warn('⚠️ OpenHarmony开发模式: 已禁用HTTPS证书验证');
    console.warn('   请仅在开发环境中使用此配置!');
    console.warn('   生产环境必须使用有效证书!');
  } catch (error) {
    console.error('OpenHarmony HTTPS配置失败:', error);
    // 可以考虑回退方案或提示用户
  }
}

// 在应用启动时调用
configureDevHttpsAgent();

💡 实现原理

  • 通过覆盖httpsAgent配置,禁用证书验证
  • checkServerIdentity设置为返回undefined,跳过主机名验证
  • 仅在开发环境启用,生产环境应移除此代码

⚠️ 重要安全警告

  1. 绝对不要在生产环境中使用rejectUnauthorized: false
  2. OpenHarmony设备在生产环境中必须使用有效的、受信任的SSL证书
  3. 对于企业内部测试,应将自签名证书添加到OpenHarmony设备的受信任证书库

网络权限与后台请求限制

OpenHarmony对后台网络请求有严格限制,这直接影响到应用的后台数据同步能力:

/**
 * OpenHarmony后台网络请求管理
 * 处理应用进入后台时的网络请求
 */
let backgroundTimer;

export function setupBackgroundNetworkHandler() {
  if (Platform.OS !== 'harmony') return;
  
  // 监听应用状态变化
  AppState.addEventListener('change', handleAppStateChange);
}

function handleAppStateChange(nextAppState) {
  if (nextAppState === 'background') {
    // OpenHarmony进入后台,设置短时间内的网络请求允许
    console.log('OpenHarmony应用进入后台,允许5秒内完成的网络请求');
    
    // 清除现有定时器
    if (backgroundTimer) {
      clearTimeout(backgroundTimer);
    }
    
    // 5秒后强制取消所有进行中的请求
    backgroundTimer = setTimeout(() => {
      console.warn('OpenHarmony后台超时,取消所有网络请求');
      cancelAllRequests();
    }, 5000);
  } else if (nextAppState === 'active') {
    // 应用回到前台,清除定时器
    if (backgroundTimer) {
      clearTimeout(backgroundTimer);
      backgroundTimer = null;
    }
  }
}

// 请求取消功能实现
const pendingRequests = new Map();

api.interceptors.request.use(config => {
  const source = CancelToken.source();
  config.cancelToken = source.token;
  const requestId = `${config.url}_${Date.now()}`;
  pendingRequests.set(requestId, source);
  config.requestId = requestId;
  return config;
});

api.interceptors.response.use(response => {
  if (response.config.requestId) {
    pendingRequests.delete(response.config.requestId);
  }
  return response;
}, error => {
  if (error.config?.requestId) {
    pendingRequests.delete(error.config.requestId);
  }
  return Promise.reject(error);
});

function cancelAllRequests() {
  pendingRequests.forEach(source => {
    source.cancel('应用进入后台,取消网络请求');
  });
  pendingRequests.clear();
}

💡 代码解析

  • 使用AppState监听应用状态变化
  • 进入后台后设置短暂宽限期(5秒)
  • 超时后取消所有进行中的请求
  • 使用CancelToken实现请求取消

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony对后台任务限制严格,通常只有几秒的执行时间
  2. 必须及时取消网络请求,避免触发系统限制
  3. 请求取消消息应明确,便于调试

性能优化与内存管理

在资源受限的OpenHarmony设备上,网络请求层的性能优化尤为重要:

/**
 * OpenHarmony网络性能优化配置
 */
export function configureApiPerformance() {
  if (Platform.OS !== 'harmony') return;
  
  // 1. 限制并发请求数(OpenHarmony设备资源有限)
  api.defaults.maxContentLength = 50 * 1024; // 50KB
  api.defaults.maxBodyLength = 100 * 1024;   // 100KB
  
  // 2. 配置连接池(减少TCP握手开销)
  const http = require('http');
  const https = require('https');
  
  api.defaults.httpAgent = new http.Agent({ 
    keepAlive: true,
    maxSockets: 5,
    timeout: 30000
  });
  
  api.defaults.httpsAgent = new https.Agent({ 
    keepAlive: true,
    maxSockets: 5,
    timeout: 30000,
    rejectUnauthorized: true
  });
  
  // 3. 响应缓存(简单实现)
  const cache = new Map();
  const CACHE_TTL = 60 * 1000; // 60秒
  
  api.interceptors.request.use(config => {
    if (config.method === 'get' && config.cache) {
      const cacheKey = `${config.url}_${JSON.stringify(config.params)}`;
      const cached = cache.get(cacheKey);
      
      if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
        // 创建模拟响应
        const response = {
          data: cached.data,
          status: 200,
          statusText: 'OK',
          headers: {},
          config,
          request: {}
        };
        return Promise.resolve(response);
      }
    }
    return config;
  });
  
  api.interceptors.response.use(response => {
    if (response.config.method === 'get' && response.config.cache) {
      const cacheKey = `${response.config.url}_${JSON.stringify(response.config.params)}`;
      cache.set(cacheKey, {
        data: response.data,
        timestamp: Date.now()
      });
    }
    return response;
  });
}

💡 代码解析

  • 限制请求/响应大小,避免内存溢出
  • 配置HTTP连接池,减少网络开销
  • 实现简单的GET请求缓存机制
  • 针对OpenHarmony设备资源进行优化

⚠️ OpenHarmony平台适配要点

  1. OpenHarmony设备内存通常有限,需严格控制请求大小
  2. 连接池配置应根据设备性能调整(低端设备减少maxSockets)
  3. 缓存机制需考虑OpenHarmony的存储限制,避免占用过多空间

实战案例:构建企业级API服务层

项目结构设计

在实际项目中,应将网络层组织为清晰的模块化结构:

src/
├── api/
│   ├── index.js          # API主入口
│   ├── auth.js           # 认证相关API
│   ├── users.js          # 用户管理API
│   ├── products.js       # 产品相关API
│   └── ...               # 其他业务模块
├── utils/
│   ├── api.js            # Axios实例配置
│   ├── interceptors.js   # 拦截器配置
│   └── auth.js           # 认证服务
└── services/
    └── apiService.js     # 高层API服务封装

这种结构将网络请求分为三层:

  1. 基础层:Axios实例和拦截器配置
  2. 服务层:业务API定义
  3. 应用层:业务逻辑调用

拦截器完整实现

结合前文内容,下面是完整的拦截器配置文件:

/**
 * 拦截器配置 - OpenHarmony优化版
 * 包含请求/响应拦截器的完整实现
 */
import api from './api';
import { checkNetworkConnection, configureDevHttpsAgent } from './network';
import { AuthService } from './auth';

// 配置开发环境HTTPS(仅开发模式)
configureDevHttpsAgent();

// 请求拦截器
api.interceptors.request.use(
  async (config) => {
    // 1. 检查网络连接
    const isConnected = await checkNetworkConnection();
    if (!isConnected) {
      return Promise.reject(new Error('网络不可用'));
    }
    
    // 2. 添加认证token
    if (config.url !== '/auth/login' && config.url !== '/auth/refresh') {
      try {
        const token = await AuthService.getValidToken();
        config.headers.Authorization = `Bearer ${token}`;
      } catch (error) {
        return Promise.reject(error);
      }
    }
    
    // 3. 添加设备信息
    config.headers['X-Device-Info'] = JSON.stringify({
      platform: Platform.OS,
      model: DeviceInfo.getModel(),
      apiLevel: await getApiLevel(),
      deviceId: await DeviceInfo.getDeviceId(),
      appVersion: DeviceInfo.getApplicationName()
    });
    
    // 4. 请求ID用于追踪
    config.headers['X-Request-ID'] = generateRequestId();
    
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
api.interceptors.response.use(
  (response) => {
    // 统一返回数据结构
    if (response.data && response.data.code === 200) {
      return response.data.data;
    }
    return response.data;
  },
  async (error) => {
    // 标准化错误对象
    const apiError = {
      message: error.response?.data?.message || error.message,
      code: error.response?.status || 'NETWORK_ERROR',
      originalError: error
    };
    
    // OpenHarmony特定错误处理
    if (Platform.OS === 'harmony') {
      if (error.code === 'ERR_NETWORK') {
        apiError.message = '网络连接异常,请检查网络设置';
      } else if (error.code === 'ECONNABORTED') {
        apiError.message = '请求超时,请重试';
      }
    }
    
    // 业务错误处理
    if (error.response?.data?.code) {
      apiError.businessCode = error.response.data.code;
    }
    
    // 记录错误日志(OpenHarmony优化)
    logApiError(apiError);
    
    return Promise.reject(apiError);
  }
);

// 辅助函数
function generateRequestId() {
  return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}

function logApiError(error) {
  if (!__DEV__) return;
  
  const logEntry = {
    timestamp: new Date().toISOString(),
    message: error.message,
    code: error.code,
    businessCode: error.businessCode,
    url: error.originalError?.config?.url
  };
  
  // OpenHarmony设备日志优化
  if (Platform.OS === 'harmony') {
    console.log('[API ERROR]', JSON.stringify(logEntry, null, 2));
  } else {
    console.error('[API ERROR]', logEntry);
  }
}

// 导出API实例
export default api;

💡 设计要点

  • 分层错误处理,区分网络错误和业务错误
  • 统一的请求ID便于问题追踪
  • 设备信息标准化上报
  • OpenHarmony特定的错误日志格式

测试与验证方法

在OpenHarmony设备上验证拦截器功能需要特殊方法:

/**
 * OpenHarmony拦截器测试工具
 * 用于验证拦截器在真实设备上的行为
 */
export class InterceptorTester {
  static async testAllScenarios() {
    console.log('🚀 开始OpenHarmony拦截器测试...');
    
    try {
      // 1. 测试基础请求
      await this.testBasicRequest();
      
      // 2. 测试token自动刷新
      await this.testTokenRefresh();
      
      // 3. 测试网络错误处理
      await this.testNetworkError();
      
      // 4. 测试离线队列
      await this.testOfflineQueue();
      
      console.log('✅ 所有拦截器测试通过!');
    } catch (error) {
      console.error('❌ 拦截器测试失败:', error);
      throw error;
    }
  }
  
  static async testBasicRequest() {
    console.log('🧪 测试基础请求...');
    
    try {
      const response = await api.get('/test', {
        headers: { 'X-Test-Header': 'interceptor-test' }
      });
      
      // 验证拦截器添加的头信息
      const deviceInfo = JSON.parse(response.headers['x-device-info']);
      console.log('设备信息验证:', {
        platform: deviceInfo.platform === 'harmony',
        hasApiLevel: !!deviceInfo.apiLevel
      });
      
      // OpenHarmony特定验证
      if (Platform.OS === 'harmony') {
        console.assert(
          deviceInfo.apiLevel >= 9,
          'OpenHarmony API级别应至少为9'
        );
      }
      
      console.log('✅ 基础请求测试通过');
    } catch (error) {
      console.error('❌ 基础请求测试失败:', error);
      throw error;
    }
  }
  
  // 其他测试方法...
  static async testTokenRefresh() { /* 实现token刷新测试 */ }
  static async testNetworkError() { /* 实现网络错误测试 */ }
  static async testOfflineQueue() { /* 实现离线队列测试 */ }
}

// 在开发构建中自动运行测试
if (__DEV__ && Platform.OS === 'harmony') {
  setTimeout(() => {
    console.log('🔍 运行OpenHarmony拦截器自检...');
    InterceptorTester.testAllScenarios().catch(console.error);
  }, 2000);
}

💡 测试要点

  • 针对OpenHarmony设备特性设计专用测试
  • 验证拦截器添加的自定义头信息
  • 检查OpenHarmony特有的API级别
  • 开发模式下自动运行测试,及早发现问题

⚠️ OpenHarmony平台测试要点

  1. 必须在真实OpenHarmony设备上测试,模拟器可能无法完全复现问题
  2. 测试时应覆盖不同网络状态(WiFi、蜂窝、无网络)
  3. 验证后台运行时的请求行为是否符合预期

结论

通过本文的深入探讨,我们系统性地了解了在OpenHarmony平台上使用React Native实现Axios请求拦截器的关键技术。从基础配置到高级技巧,再到OpenHarmony平台的特殊适配,每一步都经过实际项目验证,确保在真实设备上可靠运行。

关键要点总结

  1. 平台差异认知:OpenHarmony在网络权限、HTTPS处理和后台限制方面与Android/iOS有显著差异,必须针对性适配
  2. 拦截器核心价值:统一处理认证、错误、日志等,大幅提升代码质量和可维护性
  3. OpenHarmony专属配置
    • 网络权限必须在module.json5中正确声明
    • HTTPS证书处理需要特殊配置(开发环境临时方案)
    • 后台网络请求有严格时间限制,需及时取消
  4. 性能优化重点:在资源受限设备上,需控制请求大小、使用连接池和适当缓存
  5. 安全实践:生产环境绝不能禁用证书验证,token管理需严谨
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐