React Native鸿蒙开发实战(五):网络请求与数据获取

React Native鸿蒙开发实战(五):网络请求与数据获取

一、React Native网络请求基础

在React Native鸿蒙应用中,网络请求是连接前端界面与后端服务的核心桥梁。选择合适的网络请求方案,对于应用性能和用户体验至关重要。

1.1 Fetch API:官方标准方案

Fetch API是React Native内置的网络请求方案,遵循Web标准,提供简洁的Promise-based接口。在鸿蒙平台上,Fetch API经过专门优化,能够充分发挥HarmonyOS的网络能力。

复制代码
import React, { useState, useEffect } from 'react-native';

const DataFetchingComponent = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await fetch('https://api.example.com/data');
        
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) return <Text>加载中...</Text>;
  if (error) return <Text>错误: {error}</Text>;
  
  return (
    <View>
      <Text>数据: {JSON.stringify(data)}</Text>
    </View>
  );
};

关键特性

  • Promise-based:支持async/await语法,代码更简洁
  • 自动JSON解析:response.json()自动处理JSON数据转换
  • 错误处理:通过try-catch捕获网络异常
  • 超时控制:需要手动实现超时机制

1.2 鸿蒙网络权限配置

在鸿蒙平台上进行网络请求前,需要在应用配置文件中声明网络权限:

复制代码
// module.json5
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "需要网络权限获取数据"
      }
    ]
  }
}

二、高级网络请求方案

2.1 Axios:功能丰富的HTTP客户端

Axios是React Native生态中最流行的第三方网络库,提供更完善的功能和更好的错误处理机制。

复制代码
import axios from 'axios';
import { Alert } from 'react-native';

// 创建axios实例
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  }
});

// 请求拦截器
apiClient.interceptors.request.use(
  (config) => {
    // 添加认证token
    const token = await getAuthToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
apiClient.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      // 处理未授权错误
      Alert.alert('登录已过期', '请重新登录');
      redirectToLogin();
    }
    return Promise.reject(error);
  }
);

// 在组件中使用
const fetchUserData = async (userId) => {
  try {
    const response = await apiClient.get(`/users/${userId}`);
    return response.data;
  } catch (error) {
    console.error('获取用户数据失败:', error);
    throw error;
  }
};

Axios优势

  • 拦截器机制:统一处理请求和响应
  • 自动转换:自动JSON序列化/反序列化
  • 取消请求:支持请求取消功能
  • 更好的错误处理:区分网络错误和服务器错误

2.2 鸿蒙原生网络模块集成

对于需要极致性能的场景,可以直接调用鸿蒙原生网络模块:

复制代码
import { NativeModules } from 'react-native';

const { HarmonyNetworking } = NativeModules;

// 调用鸿蒙原生网络能力
const fetchWithHarmony = async (url, options) => {
  try {
    const result = await HarmonyNetworking.request({
      url,
      method: options?.method || 'GET',
      headers: options?.headers,
      body: options?.body,
    });
    return JSON.parse(result);
  } catch (error) {
    throw new Error(`鸿蒙网络请求失败: ${error.message}`);
  }
};

三、网络性能优化策略

3.1 连接池与请求合并

在鸿蒙平台上,合理的连接池配置可以显著提升网络性能。

复制代码
class OptimizedHttpClient {
  constructor() {
    this.pendingRequests = new Map();
    this.batchTimer = null;
  }

  // 批量请求处理
  async batchRequest(url, requests) {
    if (requests.length === 0) return [];
    
    // 合并相似请求
    const batchKey = `${url}-${JSON.stringify(requests[0])}`;
    
    if (this.pendingRequests.has(batchKey)) {
      return this.pendingRequests.get(batchKey);
    }

    const promise = this.executeBatch(url, requests);
    this.pendingRequests.set(batchKey, promise);

    promise.finally(() => {
      this.pendingRequests.delete(batchKey);
    });

    return promise;
  }

  async executeBatch(url, requests) {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ batch: requests })
    });
    
    return response.json();
  }
}

3.2 多级缓存策略

实现智能缓存机制,减少不必要的网络请求:

复制代码
class NetworkCache {
  constructor() {
    this.memoryCache = new Map();
    this.maxSize = 100; // 最大缓存条目数
  }

  async get(url) {
    const cacheKey = this.generateKey(url);
    
    // 1. 检查内存缓存
    if (this.memoryCache.has(cacheKey)) {
      const cached = this.memoryCache.get(cacheKey);
      if (Date.now() - cached.timestamp < 5 * 60 * 1000) { // 5分钟有效期
        return cached.data;
      }
      this.memoryCache.delete(cacheKey);
    }

    // 2. 检查持久化缓存(鸿蒙本地存储)
    try {
      const persistentData = await this.getPersistentCache(cacheKey);
      if (persistentData) {
        // 更新内存缓存
        this.setMemoryCache(cacheKey, persistentData);
        return persistentData;
      }
    } catch (error) {
      console.warn('持久化缓存读取失败:', error);
    }

    return null;
  }

  set(url, data) {
    const cacheKey = this.generateKey(url);
    
    // 更新内存缓存
    this.setMemoryCache(cacheKey, data);
    
    // 异步更新持久化缓存
    this.setPersistentCache(cacheKey, data);
  }

  setMemoryCache(key, data) {
    if (this.memoryCache.size >= this.maxSize) {
      const firstKey = this.memoryCache.keys().next().value;
      this.memoryCache.delete(firstKey);
    }
    
    this.memoryCache.set(key, {
      data,
      timestamp: Date.now()
    });
  }
}

四、实战案例:电商应用数据层设计

4.1 API服务封装

复制代码
class EcommerceApiService {
  constructor() {
    this.cache = new NetworkCache();
    this.httpClient = new OptimizedHttpClient();
  }

  // 商品列表获取
  async getProducts(categoryId, page = 1, pageSize = 20) {
    const cacheKey = `products-${categoryId}-${page}`;
    
    // 检查缓存
    const cached = await this.cache.get(cacheKey);
    if (cached) {
      return cached;
    }

    try {
      const response = await apiClient.get('/products', {
        params: { categoryId, page, pageSize }
      });

      // 缓存结果
      this.cache.set(cacheKey, response.data);
      
      return response.data;
    } catch (error) {
      throw this.handleApiError(error);
    }
  }

  // 商品详情获取
  async getProductDetail(productId) {
    const cacheKey = `product-detail-${productId}`;
    
    const cached = await this.cache.get(cacheKey);
    if (cached) {
      return cached;
    }

    try {
      const [productResponse, reviewResponse] = await Promise.all([
        apiClient.get(`/products/${productId}`),
        apiClient.get(`/products/${productId}/reviews`)
      ]);

      const productData = {
        ...productResponse.data,
        reviews: reviewResponse.data
      };

      this.cache.set(cacheKey, productData);
      return productData;
    } catch (error) {
      throw this.handleApiError(error);
    }
  }

  // 错误处理
  handleApiError(error) {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          return new Error('请重新登录');
        case 404:
          return new Error('资源不存在');
        case 500:
          return new Error('服务器错误');
        default:
          return new Error('请求失败');
      }
    } else if (error.request) {
      return new Error('网络连接失败');
    } else {
      return new Error('未知错误');
    }
  }
}

4.2 React Hook网络请求封装

复制代码
import { useState, useEffect, useCallback } from 'react';

// 自定义网络请求Hook
export const useApi = (apiFunction, immediate = true) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(immediate);
  const [error, setError] = useState(null);

  const execute = useCallback(async (...args) => {
    try {
      setLoading(true);
      setError(null);
      
      const result = await apiFunction(...args);
      setData(result);
      return result;
    } catch (err) {
      setError(err);
      throw err;
    } finally {
      setLoading(false);
    }
  }, [apiFunction]);

  useEffect(() => {
    if (immediate) {
      execute();
    }
  }, [execute, immediate]);

  return { data, loading, error, execute };
};

// 在组件中使用
const ProductList = ({ categoryId }) => {
  const apiService = useMemo(() => new EcommerceApiService(), []);
  
  const { data: products, loading, error, execute: refetch } = useApi(
    () => apiService.getProducts(categoryId),
    true
  );

  const handleRefresh = useCallback(() => {
    refetch();
  }, [refetch]);

  if (loading) return <ProductListSkeleton />;
  if (error) return <ErrorView error={error} onRetry={handleRefresh} />;

  return (
    <View>
      <FlatList
        data={products}
        renderItem={({ item }) => <ProductCard product={item} />}
        keyExtractor={item => item.id.toString()}
        onRefresh={handleRefresh}
        refreshing={loading}
      />
    </View>
  );
};

五、鸿蒙分布式网络特性

5.1 跨设备数据同步

利用鸿蒙的分布式能力,实现多设备间的数据同步。

复制代码
class DistributedDataSync {
  constructor() {
    this.connectedDevices = new Set();
  }

  // 监听设备连接
  setupDeviceListener() {
    // 注册分布式设备监听
    this.deviceManager.on('deviceConnected', (device) => {
      this.connectedDevices.add(device.id);
      this.syncDataWithDevice(device.id);
    });

    this.deviceManager.on('deviceDisconnected', (device) => {
      this.connectedDevices.delete(device.id);
    });
  }

  // 跨设备数据同步
  async syncShoppingCart(deviceId) {
    try {
      const localCart = await this.getLocalCart();
      
      const response = await fetch(`harmony://device/${deviceId}/api/cart/sync`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          cart: localCart,
          timestamp: Date.now()
        })
      });

      return response.json();
    } catch (error) {
      console.error('跨设备同步失败:', error);
    }
  }
}

六、安全最佳实践

6.1 HTTPS与证书安全

复制代码
// 安全配置示例
const secureApiClient = axios.create({
  baseURL: 'https://api.secure.com',
  httpsAgent: new https.Agent({
    // 证书验证
    rejectUnauthorized: true,
    // 证书绑定
    ca: [/* 受信任的CA证书 */]
  }),
  headers: {
    'Content-Type': 'application/json',
  }
});

// 请求签名
const signRequest = (method, url, body, timestamp) => {
  const secret = await getApiSecret();
  const signString = `${method}${url}${JSON.stringify(body)}${timestamp}`;
  return crypto.createHmac('sha256', secret).update(signString).digest('hex');
};

七、总结

通过本章学习,我们掌握了React Native在鸿蒙平台上的网络请求与数据获取完整方案。核心要点总结

  1. 基础方案:Fetch API是官方标准,Axios提供更丰富功能
  2. 性能优化:连接池、缓存策略、请求合并是提升性能的关键
  3. 鸿蒙特性:分布式网络能力支持跨设备数据同步
  4. 安全实践:HTTPS、证书绑定、请求签名确保通信安全

最佳实践建议

  • 使用拦截器统一处理认证和错误
  • 实现智能缓存减少网络请求
  • 针对鸿蒙平台优化网络配置
  • 考虑离线场景的数据同步策略

避坑指南

  • 避免在组件卸载后更新状态
  • 合理设置超时时间防止请求挂起
  • 实现请求取消机制提升用户体验

下一章我们将深入讲解原生能力调用,学习如何在React Native鸿蒙应用中调用设备原生功能,如相机、定位等硬件特性。

相关推荐
cici1587416 小时前
C#实现三菱PLC通信
java·网络·c#
专业开发者17 小时前
经 Nordic 实测:蓝牙长距离传输
网络·物联网
zfj32118 小时前
top 命令中的 wa (IO wait) 指标,理论上几乎完全是由磁盘IO(包括swap)引起的,而不是网络IO
linux·网络·top·iowait
Xの哲學18 小时前
Linux网卡注册流程深度解析: 从硬件探测到网络栈
linux·服务器·网络·算法·边缘计算
周胡杰18 小时前
鸿蒙preferences单多例使用,本地存储类
缓存·华为·harmonyos·preferences·鸿蒙本地存储
IvanCodes18 小时前
[鸿蒙2025领航者闯关] 共享终端的隐形守护者:基于 HarmonyOS 6 的全链路隐私闭环实战
华为·harmonyos·鸿蒙
Violet_YSWY18 小时前
桥接网络、net、仅宿主机三者区别
网络
携欢19 小时前
POrtSwigger靶场之Exploiting XXE using external entities to retrieve files通关秘籍
网络·安全·github
xian_wwq19 小时前
【学习笔记】OSI安全架构体系
网络·笔记·学习
heartbeat..20 小时前
Servlet 全面解析(JavaWeb 核心)
java·网络·后端·servlet