鸿蒙开发-RCP远程通信请求工具类封装
官方文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/remote-communication-customdnsconfig
模拟机 / 真机调试遇到的问题
▼json复制代码{ "code": 1007900007, "data": "Couldn't connect to server", "extendInfo": { "httpPhase": "110000", "dnsDur": "0.10", "tcpDur": "0.00", "tlsDur": "0.00", "sndDur": "0.00", "rcvDur": "0.00", "totDur": "0.66", "redDur": "0.00", "osErr": "111", "sptIP6": "0", "proxyType": "none", "sock": "98", "tcpConnE": "115", "tryConnV4": "1", "tryConnV6": "0" } }
说是无法连接到服务器。
原因分析

调试时使用的基地址为 localhost:8080,因为我们运行是在 模拟机 或 真机上,所有访问的 localhost:8080 无法映射到电脑的服务端。
解决方案
- 可以使用云服务器。
- 内网穿透。
因为只是在本地进行测试封装的RCP工具是否可用,所以用云服务器大材小用了。所以这里使用内网穿透。内网穿透有很多的方式。
- cpolar。(https://www.cpolar.com/docs)
- 路由侠。(https://www.luyouxia.com/)
- 等等。
在这里使用路由侠进行操作。将基地址换成内网穿透后的公网地址即可。
工具封装
目前实现的请求类型有:GET、POST、PUT、DELETE、FETCH。并自定义了请求拦截器和响应拦截器。
▼arkts复制代码import { rcp } from '@kit.RemoteCommunicationKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { promptAction } from '@kit.ArkUI'; export interface ApiResponse<T> { code: number message: string data: T } export class RcpUtil { // 基地址 private static BASE_URL = "http://chen.w1.luyouxia.net"; // 获取会话 private static getSession(): rcp.Session { // 会话配置 const sessionConfig: rcp.SessionConfiguration = { // 定义拦截器 interceptors: [ new RequestInterceptor(), new ResponseInterceptor() ], requestConfiguration: { security: { tlsOptions: { tlsVersion: 'TlsV1.3' } }, transfer: { timeout: { connectMs: 3600, transferMs: 6000 } } } } // 创建会话并返回 return rcp.createSession(sessionConfig); } // 关闭会话 private static closeSession(session: rcp.Session) { session.close() } // get 请求处理参数拼接 private static requestParamHandle(url: string, data: object): string { let tempUrl = url // data 参数都需要拼接到地址上,如:?a=1&b=2 if (data && Object.keys(data).length) { tempUrl += "?" + Object.keys(data).filter(key => !!data[key]).map(key => `${key}=${data[key]}`).join('&') } return tempUrl } // fetch 请求 public static fetch<T>(path: string, method: rcp.HttpMethod, data?: object): Promise<T> { let url = RcpUtil.BASE_URL + path if (method === 'GET' && data) { // GET 请求需要处理地址拼接 url = RcpUtil.requestParamHandle(url, data) } // 创建 request 请求 const request = new rcp.Request(url, method); request.content = method === 'GET' ? '' : data // 创建会话 const session = RcpUtil.getSession(); // 发起请求 return new Promise((resolve, reject) => { session.fetch(request) .then((res: rcp.Response) => { const result = res.toJSON() as ApiResponse<T> resolve(result?.data) }) .catch((err: BusinessError) => { reject(err) }) .finally(() => { RcpUtil.closeSession(session) // 关闭会话 }) }) } // get 请求 public static get<T>(path: string, param?: object): Promise<T> { let url = RcpUtil.requestParamHandle(RcpUtil.BASE_URL + path, param as object) // 创建会话 const session = RcpUtil.getSession(); // 发起请求 return new Promise((resolve, reject) => { session.get(url) .then((res: rcp.Response) => { const result = res.toJSON() as ApiResponse<T> resolve(result?.data) }) .catch((err: BusinessError) => { reject(err) }) .finally(() => { RcpUtil.closeSession(session) }) }) } // post 请求 public static post<T>(path: string, data?: object): Promise<T> { // 定义 content,请根据实际情况选择 const postContent: rcp.RequestContent = data as object // 创建会话 const session = RcpUtil.getSession(); // 发起请求 return new Promise((resolve, reject) => { session.post(RcpUtil.BASE_URL + path, postContent) .then((res: rcp.Response) => { const result = res.toJSON() as ApiResponse<T> resolve(result?.data) }) .catch((err: BusinessError) => { reject(err) }) }) } // put 请求 public static put<T>(path: string, data?: object): Promise<T> { // 定义 content,请根据实际情况选择 const putContent: rcp.RequestContent = data as object // 创建会话 const session = RcpUtil.getSession(); // 发起请求 return new Promise((resolve, reject) => { session.put(RcpUtil.BASE_URL + path, putContent) .then((res: rcp.Response) => { const result = res.toJSON() as ApiResponse<T> resolve(result?.data) }) .catch((err: BusinessError) => { reject(err) }) }) } // delete public static delete<T>(path: string): Promise<T> { // 创建会话 const session = RcpUtil.getSession(); // 发起请求 return new Promise((resolve, reject) => { session.delete(RcpUtil.BASE_URL + path) .then((res: rcp.Response) => { const result = res.toJSON() as ApiResponse<T> resolve(result?.data) }) .catch((err: BusinessError) => { reject(err) }) }) } } // 定义RequestInterceptor拦截器 class RequestInterceptor implements rcp.Interceptor { // 自定义请求处理逻辑 async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> { if (context.request.headers) { context.request.headers.authorization = 'token' } else { context.request.headers = { authorization: 'token', "content-type": 'application/json', } } return next.handle(context); } } // 定义ResponseInterceptor拦截器 class ResponseInterceptor implements rcp.Interceptor { // 自定义响应处理逻辑 async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> { const response = await next.handle(context); const result = response.toJSON() as ApiResponse<object> console.log("服务端返回结果: " + JSON.stringify(result)) if (response.statusCode === 200) { // 判断业务状态码 if (result.code === 200) { // 成功响应 return Promise.resolve(response) } else { // 失败响应 promptAction.showToast({ message: result?.message }) // 抛出异常 return Promise.reject(new Error(result.message)) } } else { // 失败响应,比如 401 // 后端通过 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 这种形式返回才会进入 return Promise.reject(response); } } }
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
