萍乡市网站建设_网站建设公司_内容更新_seo优化
2025/12/23 23:08:51 网站建设 项目流程

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();// 构建带参数的URLconst 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> {// 添加认证tokenconst 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);}
}

三、总结:网络请求的核心要点

✅ 核心知识点回顾

  1. HTTP模块基础:掌握http.createHttp()创建请求对象,支持GET、POST、PUT、DELETE等方法
  2. 请求配置:设置请求头、请求体、超时时间等参数
  3. 数据格式:支持JSON、FormData等多种数据格式
  4. 错误处理:正确处理网络异常、服务器错误、认证失败等情况
  5. 性能优化:实现请求复用、请求取消、重试机制等优化策略

⚠️ 常见问题与解决方案

  1. 网络权限问题:确保在config.json中声明ohos.permission.INTERNET权限
  2. 跨域问题:服务器需要配置CORS,或者使用代理服务器
  3. HTTPS证书问题:确保服务器使用有效的SSL证书
  4. 请求超时:合理设置超时时间,实现重试机制
  5. 内存泄漏:及时释放HTTP请求对象,避免内存泄漏

🎯 最佳实践建议

  1. 封装请求服务:将HTTP请求封装到独立的服务类中,提高代码复用性
  2. 错误统一处理:实现统一的错误处理机制,避免重复代码
  3. 请求拦截器:使用拦截器统一处理认证、日志、错误等公共逻辑
  4. 性能监控:监控网络请求性能,优化慢请求
  5. 安全考虑:敏感数据使用HTTPS加密传输,token安全存储

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询