# request **Repository Path**: yyz116/request ## Basic Information - **Project Name**: request - **Description**: HarmonyOS NEXT 远场通信服务rcp模块化封装 - **Primary Language**: TypeScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2024-11-19 - **Last Updated**: 2026-01-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # nutpi/request #### 介绍 HarmonyOS NEXT 远场服务通信rcp模块儿化封装。网络通信是最常用的功能。之前有os.http包,但HarmonyOS远场服务通信服务(RCP)是华为主推的,更强大和高效。 然而原始的远场通信(RCP)使用方式较为繁琐,让人感到不够便捷。作为一位前期从事小程序开发的开发者,我深受小程序网络访问的简单性和便利性的吸引。因此,在HarmonyOS中打造一个最简单好用的网络访问组件。 ![首页](Doc/首页.png) #### 软件架构 软件架构说明 ## 特性介绍 - 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截 - 支持全局挂载 - 支持多个全局配置实例 - 支持自定义验证器 - 支持文件上传/下载 - 支持自定义参数 - 支持拦截器 - 对参数的处理比uni.request 更强 ## 下载安装 ```shell ohpm install @nutpi/request ``` 关于rcp封装更详细的介绍,请参考[HarmonyOS NEXT远场通信RCP简单好用的模块化封装](https://blog.csdn.net/yyz_1987/article/details/143881288) ## 构建环境 DevEco Studio 5.0.1 Beta3,Build Version5.0.5.200 发布日期 2024/11/12 ## 使用说明 1. 引入依赖 ``` import HttpRequest, { HttpRequestConfig, HttpResponse } from '@nutpi/request' ``` 2. 写一个工具类(全局单例配置) ```typescript //先封装一个utils/http.ts文件 import HttpRequest, { HttpRequestConfig, HttpResponse } from '@nutpi/request' const config:HttpRequestConfig = { baseURL: "http://175.178.126.10:8000/api/v1", validateStatus: (status) => { return status >= 200 && status < 300; } } export const httpClient = new HttpRequest(config); export const setRequestConfig = () => { // 请求拦截 httpClient.requestInterceptor.onFulfilled = (config?: HttpRequestConfig) =>{ // 返回一个符合 HttpRequestConfig 类型的对象 console.debug('请求拦截') return { } } httpClient.responseInterceptor.onFulfilled = (response?: HttpResponse) =>{ // 返回一个符合 HttpResponse 类型的对象 console.debug('响应拦截') return { }as HttpResponse } } setRequestConfig(); export default httpClient; ``` 3. 使用,写api接口,变得很简单啦!有多简单?两行代码写完两个接口,清晰直观: ```typescript //zhiHuApi.ts import httpClient, { setRequestConfig } from '../../utils/http'; import { BaseResponse,ZhiNewsRespData,ZhiDetailRespData } from '../bean/ApiTypes'; // 调用setRequestConfig函数进行请求配置 //setRequestConfig(); const http = httpClient; // 获取知乎列表页api接口 export const getZhiHuNews = (date:string): Promise> => http.get('/zhihunews/'+date); // 获取知乎详情页api接口 export const getZhiHuDetail = (id:string): Promise> => http.get('/zhihudetail/'+id); ``` 4. 在UI中使用api接口: ```typescript // 组件生命周期 aboutToAppear() { Log.info('ZhiHu aboutToAppear'); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); this.currentDate = formatDate2(new Date()) //获取知乎新闻列表 //this.finished = false getZhiHuNews(this.currentDate.replace(/-/g, '')).then((res) => { Log.debug(res.data.message) Log.debug("request","res.data.code:%{public}d",res.data.code) res.data.stories.map((item, index) => { item.isShowDivider = false if (item.date !== this.previousDate) { this.previousDate = item.date; item.isShowDivider = true } }); this.zhiNews = res.data.stories for (const itm of res.data.top_stories) { this.swiperData.pushData(itm) } //this.getMoreNews(); }).catch((err:BaseResponse) => { Log.debug("request","err.data.code:%d",err.data.code) Log.debug("request",err.data.message) }); } // 组件生命周期 aboutToDisappear() { Log.info('ZhiHu aboutToDisappear'); } ``` 当然,接口的报文包体格式还是需要提前定义好的,如: ```typescript type AnyObject = Record export interface BaseResponse{ statusCode: number; errMsg:string; header?: AnyObject; data:T; } export interface ErrorResp { code: number; message: string; data: []; } // 轮播图响应数据 export interface SwiperItem{ id:string; imageUrl:string; title:string; url:string; description:string; } export interface SwiperData { code: number; message: string; data: Array; } // 热门影视请求数据 export interface HotMovieReq { start: number; count: number; city:string; } // 热门影视响应数据 interface MovieItem{ id:string; cover:string; title:string; gener:string; rate:number; } export interface MovieRespData { code: number; message: string; data: Array; count: number; start: number; total: number; title: string; } //==============================知乎日报 export interface ZhiNewsItem { id:string; image:string; title:string; url:string; hint:string; date: string; isShowDivider?: boolean; } export interface ZhiNewsRespData { code: number; message: string; stories: Array; top_stories: Array; date: string; } export type ZhiDetailItem={ types:string; value:string; } export interface ZhiDetailRespData { code: number; message: string; content: Array; title: string; author: string; bio: string; avatar: string; image: string; more: string; } ``` # nutpi/request 作者:猫哥(blog.csdn.net/qq8864) 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙原生应用,三方库60+,欢迎交流。 ###### gitee [gitee](https://gitee.com/yyz116/request "github") Example ------------ 创建实例 ``` javascript import HttpRequest, { HttpRequestConfig, HttpResponse } from '@nutpi/request' const config:HttpRequestConfig = { baseURL: "http://175.178.126.10:8000/api/v1", validateStatus: (status) => { return status >= 200 && status < 300; } } const http = new HttpRequest(config); ``` 执行` GET `请求 ``` javascript http.get('/user/login', {params: {userName: 'name', password: '123456'}}).then(res => { }).catch(err => { }) // 局部修改配置,局部配置优先级高于全局配置 http.get('/user/login', { params: {userName: 'name', password: '123456'}, /* 会加在url上 */ header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ dataType: 'json', // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token // #ifndef MP-ALIPAY responseType: 'text', // #endif // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序 // #endif // #ifdef APP-PLUS sslVerify: true, // 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) // #endif // #ifdef H5 withCredentials: false, // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) // #endif // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // setTimeout(() => { // task.abort() // }, 500) }, // 自定义验证器。statusCode必存在。非必填 validateStatus: function validateStatus(statusCode) { return statusCode >= 200 && statusCode < 300 }, // forcedJSONParsing: true, // 是否尝试将响应数据json化,默认为true。如果失败则返回原数据 }).then(res => { }).catch(err => { }) ``` 执行` POST `请求 ``` javascript http.post('/user/login', {userName: 'name', password: '123456'} ).then(res => { }).catch(err => { }) // 局部修改配置,局部配置优先级高于全局配置 http.post('/user/login', {userName: 'name', password: '123456'}, { params: {}, /* 会加在url上 */ header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ dataType: 'json', // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token // #ifndef MP-ALIPAY responseType: 'text', // #endif // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序 // #endif // #ifdef APP-PLUS sslVerify: true, // 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) // #endif // #ifdef H5 withCredentials: false, // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) // #endif // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // setTimeout(() => { // task.abort() // }, 500) }, // 自定义验证器。statusCode必存在。非必填 validateStatus: function validateStatus(statusCode) { return statusCode >= 200 && statusCode < 300 } }).then(res => { }).catch(err => { }) ``` 执行` upload `请求 ``` javascript http.upload('api/upload/img', { params: {}, /* 会加在url上 */ // #ifdef APP-PLUS || H5 files: [], // 需要上传的文件列表。使用 files 时,filePath 和 name 不生效。App、H5( 2.6.15+) // #endif // #ifdef MP-ALIPAY fileType: 'image/video/audio', // 仅支付宝小程序,且必填。 // #endif filePath: '', // 要上传文件资源的路径。 // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token name: 'file', // 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容 // #ifdef H5 || APP-PLUS timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+) // #endif header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ formData: {}, // HTTP 请求中其他额外的 form data // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // task.onProgressUpdate((res) => { // console.log('上传进度' + res.progress); // console.log('已经上传的数据长度' + res.totalBytesSent); // console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend); // // // 测试条件,取消上传任务。 // if (res.progress > 50) { // uploadTask.abort(); // } // }); }, // 是否尝试将响应数据json化。boolean 或者一个包含include的对象。非必填。默认true。include为数组,包含需要json化的method // forcedJSONParsing: {include: ['UPLOAD', 'DOWNLOAD']} }).then(res => { // 返回的res.data 已经进行JSON.parse }).catch(err => { }) ``` - 关于问问题 1. 首先请善于利用搜索引擎,不管百度,还是Google,遇到问题请先自己尝试解决。自己尝试过无法解决,再问。 2. 不要问类似为什么我的xx无法使用这种问题。请仔细阅读文档,检查代码,或者说明运行环境,把相关代码贴至评论或者发送至我的邮箱,还可以点击上面的issue提交,在里面提问,可能我在里面已经回答了。 3. 我的代码如果真的出现bug,或者你有好的建议、需求,可以提issue,我看到后会立即解决 - 如何问问题 1. 问问题之前请换位思考,如果自己要解决这个问题,需要哪些信息 2. 仔细阅读文档,检查代码 3. 说明运行环境,比如:app端 ios、android 版本号、手机机型、普遍现象还是个别现象(越详细越好) 4. 发出代码片段或者截图至邮箱(很重要) 5. 或者可以在上方的'issue提交' 里发出详细的问题描述 6. 以上都觉得解决不了你的问题,可以加QQ:`534117529` 个人网站 ------------ - 欢迎大家都来踩一踩猫哥的博客 0.0 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)