引言
为处理大量重复的代码逻辑,基于 http 封装的一套面向对象式的网络请求库,支持将请求返回的数据直接转换成指定类型的对象。本篇记录封装前后的使用对比,以及在鸿蒙 ohpm 发布三方库的操作记录。
官网的 http 案例
如下代码,是官方给出的请求案例:
// 引入包名import http from '@ohos.net.http';
// 每一个httpRequest对应一个HTTP请求任务,不可复用let httpRequest = http.createHttp();// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+httpRequest.on('headersReceive', (header) => { console.info('header: ' + JSON.stringify(header));});httpRequest.request( // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定 "EXAMPLE_URL", { method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET // 开发者根据自身业务需要添加header字段 header: { 'Content-Type': 'application/json' }, // 当使用POST请求时此字段用于传递内容 extraData: { "data": "data to send", }, expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型 usingCache: true, // 可选,默认为true priority: 1, // 可选,默认为1 connectTimeout: 60000, // 可选,默认为60000ms readTimeout: 60000, // 可选,默认为60000ms usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定 }, (err, data) => { if (!err) { // data.result为HTTP响应内容,可根据业务需要进行解析 console.info('Result:' + JSON.stringify(data.result)); console.info('code:' + JSON.stringify(data.responseCode)); // data.header为HTTP响应头,可根据业务需要进行解析 console.info('header:' + JSON.stringify(data.header)); console.info('cookies:' + JSON.stringify(data.cookies)); // 8+ // 取消订阅HTTP响应头事件 httpRequest.off('headersReceive'); // 当该请求使用完毕时,调用destroy方法主动销毁 httpRequest.destroy(); } else { console.info('error:' + JSON.stringify(err)); // 取消订阅HTTP响应头事件 httpRequest.off('headersReceive'); // 当该请求使用完毕时,调用destroy方法主动销毁。 httpRequest.destroy(); } });
复制代码
可以看到,上述请求的代码量庞大,在实际开发中,我们需要将公共的部分进行抽取封装,将可变的参数暴露到上层进行动态填充或者重写,达到简化请求代码的目标。
fast_http,一个简易面向对象式的网络库
1. 安装
ohpm install @rex/fast_https_request
复制代码
2. 导入引用
import { http } from '@kit.NetworkKit'import { HttpRequest } from '@rex/fast_https_request/Index';
复制代码
3. 定义通用数据模型
首先,我们定义一个常规返回数据模型,比如这样的 JSON 结构:
{ 'code': 100 'data': { // 里面是具体的业务模型 }}
复制代码
对应的模型我们定义如下:
/// 接口返回结果通用模型, 泛型T为具体的业务模型对象interface CommonResponseModel<T> { code: number data: T}
复制代码
4. 定义业务数据模型
定义具体的业务数据模型,也就是上述 CommponResponseModel 里的 T 泛型,例如这样
/// 具体的业务模型class ResponseModel { artistsname: string name: string picurl: string url: string
constructor( artistsname: string, name: string, picurl: string, url: string ) { this.artistsname = artistsname this.name = name this.picurl = picurl this.url = url }}
复制代码
5. 创建网络请求
声明网络请求,指定将返回结果直接转换成上面的业务模型,我们这么做:
// HttpRequest<T> 将response的返回数据直接转成指定的泛型class GetRequest extends HttpRequest<CommonResponseModel<ResponseModel>> { // 重写请求类型,默认是 POST public method: http.RequestMethod = http.RequestMethod.GET; // 重写域名domain public domain: string = 'https://api.uomg.com'; // 重写请求路径 public path: string = '/api/rand.music'; // GET 传参赋值 public getQuery: Record<string, string> = { 'sort': '热歌榜', 'format': 'json', }}
复制代码
class PostRequest extends HttpRequest<CommonResponseModel<ResponseModel>> { // 重写请求类型,默认是 POST public method: http.RequestMethod = http.RequestMethod.POST; // 重写域名domain public domain: string = 'https://api.uomg.com'; // 重写请求路径 public path: string = '/api/comments.163'; // POST 传参赋值 public postBody: Record<string, string> = { 'format': 'json', }}
复制代码
6. 发送网络请求
try { const response : CommonResponseModel<ResponseModel> = await new GetRequest().execute() let responseTxt = JSON.stringify(response); console.log(`response == ${responseTxt}`) } catch (e) { let errorMessage = JSON.stringify(e); console.log(`error == ${errorMessage}`) }
复制代码
使用上面声明的请求 new GetRequest().excute() 或者 new PostRequest().excute() 获取到的结果为 CommonResponseModel<ResponseModel> 对象
let data : ResponseModel = await new GetRequest().execute().data
复制代码
这样就获取到了我们的业务模型对象
7. 如何打印网络日志
在继承 HttpRequest 时选择重写内部三方方法,可用于分别打印 request、response、httpError
class PostRequest extends HttpRequest<T> { ....省略具体的请求 // 重写该方法打印 request protected onRequestChain(request: BaseRequestOption): void { console.log(`fast_http_request >>> url : ${this.requestUrl()}`) if (request.postBody != null){ console.log(`fast_http_request >>> POST Parmas : ${JSON.stringify(request.postBody)}`) } }
// 重写该方法打印 response protected onResponseChain(response: HttpResponse): void { console.log(`fast_http_request >>> response : ${JSON.stringify(response)}`) }
// 重写该方法打印 http error protected onErrorChain(error: Error): void { console.log(`fast_http_request >>> error : ${JSON.stringify(error)}`) }}
复制代码
8. 如何在工程中,统一管理,进行复用
我们可以按照域名定义一个通用的 CommonRequest,例如:
class CommonRequest<T> extends HttpRequest<CommonResponseModel<T>> { // 重写域名domain public domain: string = 'https://api.uomg.com'; ///这里自己把log加上,统一打印请求日志}
复制代码
遇到具体的业务时
假设我们业务接口返回的的数据,定义模型名称为 BusinessModel
class BusinessModel { /// 具体的业务字段}
复制代码
所有的业务请求,我们可以通过继承 CommonRequest,创建具体的业务请求,指定泛型即可
class BusinessRequest extends CommonRequest<BusinessModel> { // Model 是请求参数,这里我定义为 Record 类型,按照自己的需要也可以定义为其他 constructor(requestParams: Record<string, Object>){ this.postBody = requestParams; } // 重写请求路径 public path: string = '具体的url';}
复制代码
如上便完成了一个业务请求的封装, 通过 new 即可使用
let requestParams = { 'pageIndex': '1', 'keywords': 'rex',}
let request = new BusinessRequest(requestParams);
request.excute().then((data)=>{ // 这里获取的 data 类型为 CommonResponseModel<BusinessModel>})
复制代码
聊一下怎么发布到鸿蒙三方库市场
1. 创建组织
先到 OpenHarmony三方库中心仓 上面注册个账号,到 个人中心 ->组织管理 中,申请一个组织。这个组织名字以后要用到,因为普通三方作者,是不能使用 ohos 前缀的。
比如我注册的是组织名为 rex,组件为 fast_https_request。那么组件最终的名字就是 @rex/fast_https_request
最后用户可以通过 ohpm install @candies/fast_https_request,来安装使用组件。
2. 创建项目(选择静态库)
创建项目,选择静态库(Static Libray)
对应的 oh_package.json5 文件里配置的是组件的相关信息
其他字段,请查看 OpenHarmony三方库中心仓
3. 发布
在准备发布之前,请先阅读 贡献三方库 里面内容。
这里简单说一下组件内需要包含的必要的文件:
配置 oh-package.json5 文件,是对当前三方库的元数据描述
创建 README 文件,为了帮助其他人在 ohpm 上找到您的三方库
创建 CHANGELOG 文件,描述版本及更新内容
添加 LICENSE 文件,开源协议
然后将你的组件编译生成静态包 .har
生成完毕后执行命令行进行发布:
ohpm publish xxx.har
(xxx.har 为上传包的本地路径)。上传成功之后,你就可以看到你的个人中心里面的消息和状态了,耐心等待审核。
PS: 组织名申请会比较耗时
已开源,附上源码及 Example
(基于 API11 开发,支持 NEXT 及以上版本运行)已上传可供参考,包含如下内容:
静态库+动态包+多模块设计
状态管理
统一路由管理(router+navPathStack)
网络请求、Loading 等工具库封装
自定义组件、自定义弹窗(解耦)
EventBus 事件通知
扩展修饰器,实现 节流、防抖、权限申请
动态路由 (navPathStack + 动态 import + WrappedBuilder)
UI 动态节点操作 (BuilderNode + NodeController)
折叠屏适配示例
折叠屏适配示例
组件工厂示例
组件动态属性设置示例
云函数、云数据库使用示例
华为账号服务示例(快速登陆、快速验证手机号)
评论