HarmonyOS开发 - 电商App实例二( 网络请求http)

devtools/2025/3/15 1:44:22/

        在HarmonyOS中进行网络请求开发时,可以使用"@ohos.net.http"库,该库支持常见的HTTP方法,能够满足大多数应用或元服务的需求。

        接下来,我们将通过http库,对其进行二次封装,并向后台发送请求,完成banner数据的获取。

https://i-blog.csdnimg.cn/direct/42a37cc3b2f14e43aeb36d4d923dcee8.png" width="589" />

一、基本使用

1.1 导入模块

import http from '@ohos.net.http'

1.2 http请求数据

        首先,我们先看下@ohos.net.http的基本用法,使用http模块发送一个GET请求,处理响应。示例代码如下:

import http from '@ohos.net.http';// 创建 HTTP 请求对象
let httpRequest = http.createHttp();// 发送 GET 请求
httpRequest.request("https://api.example.com/data",{method: http.RequestMethod.GET,header: {'Content-Type': 'application/json'}},(err, data) => {if (err) {console.error('Error:', err);} else {console.log('Response Code:', data.responseCode);console.log('Response Data:', data.result);}}
);

1.3 HttpRequestOptions

        参数如下表:

名称

类型

描述

method

RequestMethod

请求方式:GET、POST、PUT、DELETE等

extraData

string|Object

请求参数

header

Object

请求字段

connectTimeout

number

连接超时时间,单位毫秒,默认是60000ms

readTimeout

number

读取超时时间,同上

1.4 HttpResponse

        参数如下表:

名称

类型

描述

responseCode

ResponseCode

响应状态码

header

Object

响应头

cookies

string

响应返回的cookies

result

string|Object

响应体,默认是JSON字符串

resultType

HttpDataType

返回值类型

二、Http库

        官方提供的"@ohos.net.http库,支持常见的Http方法,如 get、post、options、head、put、delete、trace、connect等,为了简化网络请求的流程,更好地复用和管理代码,我们可以对@ohos.net.http进行封装,使其更易于使用。

        在网络请求中,通常需要考虑以下几个方面:

  1. 请求方法:使用哪种Http方法(GET、POSt、PUT、DELETE)来发送请求。
  2. 请求头:设置必要的请求头,例如Content-Type、Authorization等。
  3. 请求体:对POST、PUT请求,可能需要发送请求体。请求体可以是Json数据、表单数据或文件等。
  4. 处理响应:处理网络请求过程中可能出现的错误,例如超时,网络不可用、服务器错误等。
  5. 异步处理:网络请求通常是异步的,需要使用回调、Promise、async/awai等机制来处理异步操作。
  6. 安全性:确保网络请求的安全性,例如使用HTTPS、验证证书、防止CSRF攻击等。

2.1 封装@ohos.net.http

        为了简化代码并提高复用性,可以将@ohos.net.http封装成一个工具类。先在ets目录下创建utils目录,再创建httpUtil类(路径:ets/utils/httpUtil.ts)。代码如下:

import http from '@ohos.net.http';/*** http封装类*/
export class HttpUtil {private base_url: string = '';  // 基础路径private headers: Record<string, string> | null = null; // header信息private httpRequest: http.HttpRequest; // request请求/*** 构造函数* @param url 基础路径* @param headers header信息*/constructor(url?: string, headers?: Record<string, string>) {this.httpRequest = http.createHttp()if (url) this.base_url = urlif (headers) this.headers = headers}/*** 设置基础路径* @param url*/setBaseUrl(url: string) {this.base_url = url}/*** 设置header信息* @param headers*/setHeaders(headers: Record<string, string>) {this.headers = headers}/*** 销毁 http 请求对象*/public destroy(){this.httpRequest.destroy()}/*** 发送HTTP请求* @param url 请求地址* @param method  请求方法(如GET、POST、PUT、DELETE)* @param headers 请求头* @param data  请求体(仅用于 POST/PUT)* @returns 返回响应数据*/public async request (url: string,method: http.RequestMethod = http.RequestMethod.GET,headers: Record<string, string> = {},data?: Record<string, any>): Promise<any> {// 合并基础路径const _url = this.base_url ? this.base_url + url : url// 合并header信息const _headers = this.headers ? Object.assign({}, this.headers, headers) : !headers ? {} : headersreturn new Promise((resolve, reject) => {this.httpRequest.request(_url, {method: method,header: _headers,extraData: data}, (err, response) => {if (err) {reject(err)} else {// 如果请求成功,返回正确结果,否则返回错误信息if (response.responseCode == http.ResponseCode.OK) {resolve(response.result)} else {reject('HttP Error:' + response.responseCode)}}})})}/*** 发送 GET 请求* @param url 请求地址* @param headers 请求头* @returns 返回响应数据*/public async get(url: string, headers?: Record<string, string>) : Promise<any> {return this.request(url, http.RequestMethod.GET, headers)}/*** 发送 POST请求* @param url 请求地址* @param data 请求体* @param headers 请求头* @returns 返回响应数据*/public async post(url: string, data: Record<string, any>, headers?: Record<string, string>) : Promise<any> {return this.request(url, http.RequestMethod.POST, headers, data)}
}

2.2 实例httpUtil类

        在utils目录中,再创建request请求文件(路径:ets/utils/request.ts),用于初始化http请求的基础路径和header请求类型信息,并且全局共享该实例对象。示例代码如下:

import { HttpUtil } from './httpUtil'/*** 初始化请求 实例类*/
export const httpRequest = new HttpUtil('http://test.shop.com', {'Content-Type': 'application/json'
})

2.3 api请求

        在api目录创建,创建index.ts文件,用于定义具体业务请求函数。这里向后台发送一个GET请求,用于获取banner信息。示例代码如下:

import { httpRequest } from '../utils/request'/*** 获取banner信息*/
export const getBannerInfo = async () => {return await httpRequest.get('/banner.php')
}

2.4 获取banner信息

        如下图,在页面中添加按钮,点击“获取banner信息”,向后台发送GET请求,获取banner数据。

https://i-blog.csdnimg.cn/direct/b37b195b65804567aa1a37b0e2424177.png" width="319" />

        打开pages/index.ets 页面文件,添加http请求。代码如下:

import { getBannerInfo } from '../api/index'@Entry
@Component
struct Index {@State bannerMessage: string = '';build() {RelativeContainer() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }){Text(this.bannerMessage)Button('获取banner信息').onClick(async () => {console.log('tag')await getBannerInfo().then(res => {this.bannerMessage = JSON.stringify(res)console.log('tas success', res)}).catch(() => {console.error('Error')})})}.width('100%')}.height('100%').width('100%')}
}

        但是,大家会发现Promise回调结果 res变量下方出现了波浪线,并提示错误为:Use explicit types instead of "any", "unknown" (arkts-no-any-unknown) <ArkTSCheck>。这是因为在ArkTS中,使用any或unknow 类型会降低代码的类型的安全性,因此需要使用显式类来替代它们,确保类型安全。

https://i-blog.csdnimg.cn/direct/3eadba860b9246d5a346a72a04b2b282.png" width="632" />

2.5 定义接口

        下面为请求和响应的数据类型定义明确的接口,并使用泛型来增强类型安全性。在types目录中创建http.d.ts文件,用于定义http的接口。代码如下:

import http from '@ohos.net.http';// 定义请求参数接口
interface RequestOptions {url: string;method?: http.RequestMethod,headers?: Record<string, string>;data?: Record<string, any>;timeout?: number
}// 定义响应数据接口
interface HttpResponse<T> {responseCode: number;result: T;
}

2.6 httpUtil改造

       将定义的接口数据引入到httpUtil.ts中,对request、get、post等方法,增加泛型,通过显示类类型定义,确保请求和响应的数据类型一致。改造后的httpUtils 代码如下:

import http from '@ohos.net.http';
import { HttpResponse, RequestOptions } from '../types/http';/*** http封装类*/
export class HttpUtil {private base_url: string = '';  // 基础路径private headers: Record<string, string> | null = null; // header信息private httpRequest: http.HttpRequest; // request请求/*** 构造函数* @param url 基础路径* @param headers header信息*/constructor(url?: string, headers?: Record<string, string>) {this.httpRequest = http.createHttp()if (url) this.base_url = urlif (headers) this.headers = headers}/*** 设置基础路径* @param url*/setBaseUrl(url: string) {this.base_url = url}/*** 设置header信息* @param headers*/setHeaders(headers: Record<string, string>) {this.headers = headers}/*** 销毁 http 请求对象*/public destroy(){this.httpRequest.destroy()}/*** 发送HTTP请求* @param options 请求参数* @returns 返回响应数据*/public async request <T> (options : RequestOptions ): Promise<T> {// 合并基础路径const _url = this.base_url ? this.base_url + options.url : options.url// 合并header信息const _headers = this.headers ? Object.assign({}, this.headers, options.headers) :!options.headers ? {} : options.headersreturn new Promise((resolve, reject) => {this.httpRequest.request(_url, {method: options.method || http.RequestMethod.GET,header: _headers,extraData: options.data || {},readTimeout: options.timeout || 5000,connectTimeout: options.timeout || 5000}, (err, response) => {if (err) {reject(err)} else {// 如果请求成功,返回正确结果,否则返回错误信息if (response.responseCode == http.ResponseCode.OK) {resolve(response.result as T)} else {reject('HttP Error:' + response.responseCode)}}})})}/*** 发送 GET 请求* @param url 请求地址* @param headers 请求头* @returns 返回响应数据*/public async get <T> (url: string, headers?: Record<string, string>) : Promise<T> {return this.request <T> ({url, method: http.RequestMethod.GET, headers})}/*** 发送 POST请求* @param url 请求地址* @param data 请求体* @param headers 请求头* @returns 返回响应数据*/public async post <T> (url: string, data: Record<string, any>, headers?: Record<string, string>) : Promise<T> {return this.request({url, method: http.RequestMethod.POST, headers, data })}
}

2.7 api更改

        定义banner信息数据类型,在发起get请求位置,将类型传入进去。代码如下:

interface apiBanner {id: number;name: string;thumb: string;uid: number;createTime: Date;updateTime: Date;
}/*** 获取banner信息*/
export const getBannerInfo = async () => {return await httpRequest.get<apiBanner>('/banner.php')
}

        当httpUtil类和api请求改造好后,在页面中点击按钮,获取banner信息。如下图:

https://i-blog.csdnimg.cn/direct/ef7dd87adbf04b1a8204daa7a2275dae.png" width="293" />https://i-blog.csdnimg.cn/direct/8d462159768d400f81bc3c6f7c05b1b5.png" width="260" />

        点击按钮后,getBannerInfo接口向后台发送了一个请求,成功获取了接口响应的数据,并通过Text组件将数据显示在App界面中。

        在项目开发中,Http请求扮演着至关重要的角色,http请求是App与服务器之间进行数据交互的主要方式。通过发送http请求,App可以从服务器获取数据,如用户信息,产品信息等,也可以向服务器提交数据,如表单数据,文件上传等。这种数据交互是App实现各种功能的基础。

        如果你有更多问题,欢迎随时沟通交流!


http://www.ppmy.cn/devtools/167168.html

相关文章

Docker 基础命令 - 以 Nginx 实战总结

前言 操作镜像&#xff1a;Nginx操作环境&#xff1a;CentOS 7 64Docker版本&#xff1a;1.13.1 1. 在宿主机安装 Docker 软件 可以博主写的另外一篇博客&#xff0c;地址&#xff1a;CentOS 7 64 安装 Docker 2.Docker 基本命令 2.1 拉取 Nginx 镜像 # 搜索镜像 docker s…

leetcode日记(96)有序链表转换二叉搜索树

这么多天以来学到最多的一道题。 这题真的是把链表和树的知识综合起来了&#xff0c;需要融会贯通。 有两种做法&#xff0c;很遗憾自己写的时候一种都没想出来&#xff0c;只想到将链表先转换为数组这种简单方法…… 第一个知识点是快慢指针&#xff0c;这种做法在找出长链…

Android的tablayout+ViewPager2,缓存的数量有容量上限吗?

Android的tablayoutViewPager2&#xff0c;ViewPager2里面有6个fragment&#xff0c;不断切换不同的tab&#xff0c;那么ViewPager2会缓存6个fragment吗&#xff0c;还是缓存的数量有容量上限&#xff1f; DeepSeek R1 思考 61 秒 思考过程 好的&#xff0c;我现在要回答用户…

java学习总结(四):MyBatis

一、MyBatis介绍 像MyBatis、Hibernate都是属于ORM框架 对象关系映射&#xff08;英语&#xff1a;(Object Relational Mapping&#xff0c;简称ORM) MySql、Oracle、SqlServer都是关系型数据库 1、O->R add/insert/save studentDao.insert(student) 把一个java对象保…

React hook钩子性能优化Hooks的面试常考题目

根据,提到了常用的Hooks有useState、useEffect、useContext、useReducer、useCallback、useMemo、useRef,还有其他如useLayoutEffect和useImperativeHandle。和也提到了类似的Hooks,并且强调了useEffect的重要性。详细解释了useState、useEffect、useMemo和useCallback的区别…

PHP与数据库连接常见问题及解决办法

PHP与数据库连接常见问题及解决办法 在现代Web开发中&#xff0c;PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统&#xff08;CMS&#xff09;还是电子商务平台&#xff0c;PHP与数据库的交互都是核心功能之一。然而&#xff0c;在实际开发过程中&am…

第27周JavaSpringboot 前后端联调

电商前后端联调课程笔记 一、项目启动与环境搭建 1.1 项目启动 在学习电商项目的前后端联调之前&#xff0c;需要先掌握如何启动项目。项目启动是整个开发流程的基础&#xff0c;只有成功启动项目&#xff0c;才能进行后续的开发与调试工作。 1.1.1 环境安装 环境安装是项…

SpringBoot3+Lombok如何配置logback输出日志到文件

Background/Requirement SpringBoot3Lombok如何配置logback输出日志到文件&#xff0c;因为我需要对这些日志进行输出&#xff0c;控制台输出和文件输出&#xff0c;文件输出是为了更好的作为AuditLog且支持滚动式备份&#xff0c;每天一个文件。 Technical Solution 1.确保你…