news 2026/1/29 20:24:36

Harmony之路:网络请求——HTTP模块与数据交互

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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); } }

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

✅ 核心知识点回顾

  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安全存储
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/28 17:38:13

React 状态管理:Zustand 快速上手指南

React 状态管理:Zustand 快速上手指南 🤔 为什么需要 Zustand? 在 React 应用开发中,随着应用规模的扩大,组件间的状态管理会变得越来越复杂。传统的 useState 和 useContext 在处理全局状态或复杂状态逻辑时,可能会遇到以下问题: 状态更新复杂,需要手动处理引用比较…

作者头像 李华
网站建设 2026/1/29 13:33:10

React 状态管理:Jotai 快速上手指南

React 状态管理:Jotai 快速上手指南 🤔 为什么需要 Jotai? 在 React 应用开发中,我们经常会遇到以下状态管理难题: 全局状态管理过于复杂,需要大量的样板代码 组件间状态共享需要多层嵌套的 Context 状态更新可能导致不必要的组件重新渲染 原子状态与派生状态的管理不…

作者头像 李华
网站建设 2026/1/26 22:32:47

React 状态管理:Redux Toolkit 快速上手指南

React 状态管理:Redux Toolkit 快速上手指南 🤔 为什么需要 Redux Toolkit? Redux 是 React 生态中最流行的状态管理库之一,但传统的 Redux 开发存在以下问题: 样板代码过多,开发效率低 配置复杂,需要多个依赖(如 Redux DevTools、Thunk 等) 容易出错,需要手动处理…

作者头像 李华
网站建设 2026/1/29 14:28:37

程序员转网络安全!90 天吃透内网渗透 + 漏洞分析,直接上手

前言 有人说&#xff1a;”黑客到底比程序员高在哪&#xff0c;为什么很多人开始转行了“其实黑客都是程序员&#xff0c;但是并不是所有的程序员都是黑客. 从企业和社会需求来看&#xff0c;现在真不缺程序猿 &#xff0c;反而大量的缺安全工程师 &#xff0c;同样8000块月薪…

作者头像 李华
网站建设 2026/1/26 15:15:50

网络安全必学!撞库攻击从入门到精通,小白直接上手!

1、 撞库的原理和危害 “撞库”&#xff08;Credential Stuffing Attack&#xff09;在网络安全中是一个古老的概念&#xff0c;按中文的字面意思解读&#xff0c;就是“碰撞数据库”的意思。“碰撞”意味着碰运气&#xff0c;即不一定能成功&#xff1b;而“数据库”中往往存…

作者头像 李华