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在鸿蒙平台上的网络请求与数据获取完整方案。核心要点总结:
- 基础方案:Fetch API是官方标准,Axios提供更丰富功能
- 性能优化:连接池、缓存策略、请求合并是提升性能的关键
- 鸿蒙特性:分布式网络能力支持跨设备数据同步
- 安全实践:HTTPS、证书绑定、请求签名确保通信安全
最佳实践建议:
- 使用拦截器统一处理认证和错误
- 实现智能缓存减少网络请求
- 针对鸿蒙平台优化网络配置
- 考虑离线场景的数据同步策略
避坑指南:
- 避免在组件卸载后更新状态
- 合理设置超时时间防止请求挂起
- 实现请求取消机制提升用户体验
下一章我们将深入讲解原生能力调用,学习如何在React Native鸿蒙应用中调用设备原生功能,如相机、定位等硬件特性。