Harmony之路:网络请求——HTTP模块与数据交互
Harmony之路:网络请求——HTTP模块与数据交互
一、引入:为什么需要网络请求?
在现代移动应用中,几乎所有的应用都需要与服务器进行数据交互,无论是获取新闻列表、用户登录、上传图片还是同步数据,都离不开网络请求。HarmonyOS提供了HTTP模块作为网络请求的核心能力,支持GET、POST、PUT、DELETE等多种HTTP方法,能够满足各种网络通信需求。掌握HTTP模块的使用,是构建完整应用的必要技能。
二、讲解:HTTP模块的核心用法
1. HTTP模块基础配置
在使用HTTP模块前,需要先在应用的配置文件中声明网络权限。
config.json权限配置:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
2. 创建HTTP请求
创建HTTP请求示例:
import http from '@ohos.net.http';
// 创建HTTP请求对象
const httpRequest = http.createHttp();
// 设置请求超时时间(可选)
httpRequest.setTimeout(10000); // 10秒超时
3. GET请求
GET请求用于从服务器获取数据,是最常用的请求方法。
GET请求示例:
import http from '@ohos.net.http';
@Entry
@Component
struct GetExample {
@State data: string = '';
async fetchData() {
try {
const httpRequest = http.createHttp();
// 发起GET请求
const response = await httpRequest.request(
'https://jsonplaceholder.typicode.com/posts/1',
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
}
}
);
// 检查响应状态
if (response.responseCode === 200) {
const result = JSON.parse(response.result);
this.data = JSON.stringify(result, null, 2);
console.log('请求成功:', result);
} else {
console.error('请求失败:', response.responseCode);
this.data = `请求失败: ${response.responseCode}`;
}
} catch (error) {
console.error('请求异常:', error);
this.data = `请求异常: ${error.message}`;
}
}
build() {
Column({ space: 20 }) {
Button('发起GET请求')
.onClick(() => {
this.fetchData();
})
Text(this.data)
.fontSize(14)
.textAlign(TextAlign.Start)
.width('90%')
.height(300)
.border({ width: 1, color: Color.Gray })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
4. POST请求
POST请求用于向服务器提交数据,常用于创建资源或提交表单。
POST请求示例:
import http from '@ohos.net.http';
@Entry
@Component
struct PostExample {
@State result: string = '';
async submitData() {
try {
const httpRequest = http.createHttp();
// 请求数据
const requestData = {
title: 'foo',
body: 'bar',
userId: 1
};
// 发起POST请求
const response = await httpRequest.request(
'https://jsonplaceholder.typicode.com/posts',
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify(requestData)
}
);
if (response.responseCode === 201) {
const result = JSON.parse(response.result);
this.result = JSON.stringify(result, null, 2);
console.log('创建成功:', result);
} else {
console.error('创建失败:', response.responseCode);
this.result = `创建失败: ${response.responseCode}`;
}
} catch (error) {
console.error('请求异常:', error);
this.result = `请求异常: ${error.message}`;
}
}
build() {
Column({ space: 20 }) {
Button('发起POST请求')
.onClick(() => {
this.submitData();
})
Text(this.result)
.fontSize(14)
.textAlign(TextAlign.Start)
.width('90%')
.height(300)
.border({ width: 1, color: Color.Gray })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
5. PUT和DELETE请求
PUT用于更新资源,DELETE用于删除资源。
PUT和DELETE请求示例:
import http from '@ohos.net.http';
class ApiService {
private httpRequest: http.HttpRequest;
constructor() {
this.httpRequest = http.createHttp();
}
// 更新资源
async updatePost(id: number, data: any) {
try {
const response = await this.httpRequest.request(
`https://jsonplaceholder.typicode.com/posts/${id}`,
{
method: http.RequestMethod.PUT,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify(data)
}
);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else {
throw new Error(`更新失败: ${response.responseCode}`);
}
} catch (error) {
throw error;
}
}
// 删除资源
async deletePost(id: number) {
try {
const response = await this.httpRequest.request(
`https://jsonplaceholder.typicode.com/posts/${id}`,
{
method: http.RequestMethod.DELETE
}
);
if (response.responseCode === 200) {
return { success: true };
} else {
throw new Error(`删除失败: ${response.responseCode}`);
}
} catch (error) {
throw error;
}
}
}
6. 请求头设置
设置请求头可以传递认证信息、内容类型等。
请求头设置示例:
import http from '@ohos.net.http';
async function requestWithHeaders() {
const httpRequest = http.createHttp();
const response = await httpRequest.request(
'https://api.example.com/data',
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token-here',
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json'
}
}
);
return response;
}
7. 请求参数
GET请求可以通过URL参数传递数据,POST请求可以通过extraData传递数据。
URL参数示例:
import http from '@ohos.net.http';
async function requestWithParams() {
const httpRequest = http.createHttp();
// 构建带参数的URL
const params = new URLSearchParams({
page: '1',
limit: '10',
sort: 'desc'
});
const url = `https://api.example.com/posts?${params.toString()}`;
const response = await httpRequest.request(
url,
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
}
}
);
return response;
}
8. 文件上传
使用FormData格式上传文件。
文件上传示例:
import http from '@ohos.net.http';
import fileio from '@ohos.fileio';
async function uploadFile(filePath: string) {
const httpRequest = http.createHttp();
// 读取文件内容
const fileContent = await fileio.readText(filePath);
// 构建FormData(简化版,实际需要更复杂的处理)
const formData = `------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
${fileContent}
------WebKitFormBoundary7MA4YWxkTrZu0gW--`;
const response = await httpRequest.request(
'https://api.example.com/upload',
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
},
extraData: formData
}
);
return response;
}
9. 实际应用场景
场景1:用户登录
import http from '@ohos.net.http';
import preferences from '@ohos.data.preferences';
class AuthService {
private httpRequest: http.HttpRequest;
private preferences: preferences.Preferences;
constructor(context: common.UIAbilityContext) {
this.httpRequest = http.createHttp();
this.preferences = preferences.getPreferencesSync(context, 'authData');
}
async login(username: string, password: string): Promise<boolean> {
try {
const response = await this.httpRequest.request(
'https://api.example.com/auth/login',
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: JSON.stringify({ username, password })
}
);
if (response.responseCode === 200) {
const result = JSON.parse(response.result);
// 保存token和用户信息
await this.preferences.put('token', result.token);
await this.preferences.put('userInfo', JSON.stringify(result.user));
return true;
} else {
throw new Error('登录失败');
}
} catch (error) {
console.error('登录异常:', error);
return false;
}
}
async logout() {
try {
const token = await this.preferences.get('token', '');
if (token) {
await this.httpRequest.request(
'https://api.example.com/auth/logout',
{
method: http.RequestMethod.POST,
header: {
'Authorization': `Bearer ${token}`
}
}
);
}
// 清除本地数据
await this.preferences.delete('token');
await this.preferences.delete('userInfo');
} catch (error) {
console.error('退出登录异常:', error);
}
}
async getToken(): Promise<string> {
return await this.preferences.get('token', '');
}
}
场景2:获取列表数据
import http from '@ohos.net.http';
class DataService {
private httpRequest: http.HttpRequest;
constructor() {
this.httpRequest = http.createHttp();
}
async getPosts(page: number = 1, limit: number = 10): Promise<any[]> {
try {
const params = new URLSearchParams({
page: page.toString(),
limit: limit.toString()
});
const url = `https://jsonplaceholder.typicode.com/posts?${params.toString()}`;
const response = await this.httpRequest.request(
url,
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
}
}
);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else {
throw new Error(`获取数据失败: ${response.responseCode}`);
}
} catch (error) {
console.error('获取数据异常:', error);
throw error;
}
}
async getPostDetail(id: number): Promise<any> {
try {
const response = await this.httpRequest.request(
`https://jsonplaceholder.typicode.com/posts/${id}`,
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
}
}
);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else {
throw new Error(`获取详情失败: ${response.responseCode}`);
}
} catch (error) {
console.error('获取详情异常:', error);
throw error;
}
}
}
场景3:带认证的请求
import http from '@ohos.net.http';
import preferences from '@ohos.data.preferences';
class SecureApiService {
private httpRequest: http.HttpRequest;
private preferences: preferences.Preferences;
constructor(context: common.UIAbilityContext) {
this.httpRequest = http.createHttp();
this.preferences = preferences.getPreferencesSync(context, 'authData');
}
private async getAuthHeader(): Promise<any> {
const token = await this.preferences.get('token', '');
return {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
};
}
async getUserProfile(): Promise<any> {
try {
const headers = await this.getAuthHeader();
const response = await this.httpRequest.request(
'https://api.example.com/user/profile',
{
method: http.RequestMethod.GET,
header: headers
}
);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else if (response.responseCode === 401) {
// token过期,需要重新登录
throw new Error('认证失败,请重新登录');
} else {
throw new Error(`获取用户信息失败: ${response.responseCode}`);
}
} catch (error) {
console.error('获取用户信息异常:', error);
throw error;
}
}
async updateUserProfile(data: any): Promise<any> {
try {
const headers = await this.getAuthHeader();
const response = await this.httpRequest.request(
'https://api.example.com/user/profile',
{
method: http.RequestMethod.PUT,
header: headers,
extraData: JSON.stringify(data)
}
);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else if (response.responseCode === 401) {
throw new Error('认证失败,请重新登录');
} else {
throw new Error(`更新用户信息失败: ${response.responseCode}`);
}
} catch (error) {
console.error('更新用户信息异常:', error);
throw error;
}
}
}
10. 错误处理与重试机制
错误处理示例:
import http from '@ohos.net.http';
class ApiClient {
private httpRequest: http.HttpRequest;
constructor() {
this.httpRequest = http.createHttp();
}
async requestWithRetry(
url: string,
options: http.HttpRequestOptions,
maxRetries: number = 3
): Promise<http.HttpResponse> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await this.httpRequest.request(url, options);
if (response.responseCode >= 200 && response.responseCode < 300) {
return response;
}
// 如果是服务器错误,重试
if (response.responseCode >= 500) {
console.warn(`服务器错误,第${attempt}次重试: ${response.responseCode}`);
await this.delay(1000 * attempt); // 指数退避
continue;
}
// 客户端错误,不重试
throw new Error(`请求失败: ${response.responseCode}`);
} catch (error) {
lastError = error;
console.warn(`网络异常,第${attempt}次重试:`, error.message);
if (attempt < maxRetries) {
await this.delay(1000 * attempt);
}
}
}
throw lastError || new Error('请求失败');
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
11. 性能优化与最佳实践
1. 请求复用
import http from '@ohos.net.http';
// 单例模式管理HTTP请求
class HttpManager {
private static instance: HttpManager;
private httpRequest: http.HttpRequest;
private constructor() {
this.httpRequest = http.createHttp();
this.httpRequest.setTimeout(10000);
}
static getInstance(): HttpManager {
if (!HttpManager.instance) {
HttpManager.instance = new HttpManager();
}
return HttpManager.instance;
}
async request(url: string, options: http.HttpRequestOptions): Promise<http.HttpResponse> {
return await this.httpRequest.request(url, options);
}
}
2. 请求取消
import http from '@ohos.net.http';
class CancelableRequest {
private httpRequest: http.HttpRequest;
private isCanceled: boolean = false;
constructor() {
this.httpRequest = http.createHttp();
}
async request(url: string, options: http.HttpRequestOptions): Promise<http.HttpResponse> {
if (this.isCanceled) {
throw new Error('请求已取消');
}
try {
const response = await this.httpRequest.request(url, options);
if (this.isCanceled) {
throw new Error('请求已取消');
}
return response;
} catch (error) {
if (this.isCanceled) {
throw new Error('请求已取消');
}
throw error;
}
}
cancel() {
this.isCanceled = true;
// 注意:目前HTTP模块不支持直接取消请求,需要手动标记
}
}
3. 请求拦截器
import http from '@ohos.net.http';
import preferences from '@ohos.data.preferences';
class InterceptorService {
private httpRequest: http.HttpRequest;
private preferences: preferences.Preferences;
constructor(context: common.UIAbilityContext) {
this.httpRequest = http.createHttp();
this.preferences = preferences.getPreferencesSync(context, 'authData');
}
// 请求拦截器
private async requestInterceptor(options: http.HttpRequestOptions): Promise<http.HttpRequestOptions> {
// 添加认证token
const token = await this.preferences.get('token', '');
if (token) {
options.header = options.header || {};
options.header['Authorization'] = `Bearer ${token}`;
}
// 添加公共请求头
options.header = {
'Content-Type': 'application/json',
'User-Agent': 'MyApp/1.0',
...options.header
};
return options;
}
// 响应拦截器
private responseInterceptor(response: http.HttpResponse): http.HttpResponse {
if (response.responseCode === 401) {
// token过期处理
this.handleTokenExpired();
throw new Error('认证过期,请重新登录');
}
return response;
}
private handleTokenExpired() {
// 清除token,跳转到登录页
this.preferences.delete('token');
// router.replaceUrl({ url: 'pages/LoginPage' });
}
async request(url: string, options: http.HttpRequestOptions): Promise<http.HttpResponse> {
const processedOptions = await this.requestInterceptor(options);
const response = await this.httpRequest.request(url, processedOptions);
return this.responseInterceptor(response);
}
}
三、总结:网络请求的核心要点
✅ 核心知识点回顾
- HTTP模块基础:掌握http.createHttp()创建请求对象,支持GET、POST、PUT、DELETE等方法
- 请求配置:设置请求头、请求体、超时时间等参数
- 数据格式:支持JSON、FormData等多种数据格式
- 错误处理:正确处理网络异常、服务器错误、认证失败等情况
- 性能优化:实现请求复用、请求取消、重试机制等优化策略
⚠️ 常见问题与解决方案
- 网络权限问题:确保在config.json中声明ohos.permission.INTERNET权限
- 跨域问题:服务器需要配置CORS,或者使用代理服务器
- HTTPS证书问题:确保服务器使用有效的SSL证书
- 请求超时:合理设置超时时间,实现重试机制
- 内存泄漏:及时释放HTTP请求对象,避免内存泄漏
🎯 最佳实践建议
- 封装请求服务:将HTTP请求封装到独立的服务类中,提高代码复用性
- 错误统一处理:实现统一的错误处理机制,避免重复代码
- 请求拦截器:使用拦截器统一处理认证、日志、错误等公共逻辑
- 性能监控:监控网络请求性能,优化慢请求
- 安全考虑:敏感数据使用HTTPS加密传输,token安全存储

浙公网安备 33010602011771号