当前位置: 首页 > article >正文

HarmonyOS开发5.0【rcp网络请求】

一 概述

现在鸿蒙的网络还不成熟,所以咱们需要对网络请求框架二次封装,并且避免业务方直接引用到,预防当有比较新的成熟性价比高的框架的替换,这个过程肯定是不可避免的

1.1 第三方比如

  • [axios]的js库迁移过来的
  • [httpclient]通过socket,基于android中著名的 [okhttp]的代码写的

1.2 官方的

http和rcp的区别

  • [@ohos.net.http]暂不会再演进或新增其他功能
  • [rcp] 在接口易用性、性能、功耗方面比http网络库好,以后主推这个,但是也不确定后续是否还会出来第三套

二 [@ohos.request (上传下载)]

如果对上传和下载高度定制的,可以使用 [@ohos.request (上传下载)],如果不想有通知显示,可以mode: request.agent.Mode.FOREGROUND就可以关闭通知栏显示

二 rcp

同一个session ,没有请求限制,经过测试没有请求限制,一个App最多能创建16个session,再创建就会报错,所以我们整个APP需要两个session即可,一个是请求接口,一个是下载上传使用。

先说坑点

  • 坑1:downloadToFile 无法暂停,好像也符合设计,如果是大文件可以使用 [@ohos.request (上传下载)]mode: request.agent.Mode.FOREGROUND
  • 坑2:get请求,没有直接可以传递参数的,得咱们自己拼接到url上面

二次分装 HttpHelper,暂时不写接口隔离的方式了,

  • baseUrl

  • sessionHelper 主要提供session,一般上传下载的session 不能同时进行两个,因为回调无法分开,

  • headers 咱们请求的一些公共header

    • User-Agent: 提供关于客户端软件的信息,例如浏览器类型和版本

    • Accept: 客户端可接受的内容类型 ,例如 application/json

    • Accept-Encoding: 客户端可接受的编码方式,如gzip,br

    • Content-Type: 它告诉服务 如何解析和处理请求

        1. application/json 表示请求或响应体中的数据是 JSON 格式
        1. application/x-www-form-urlencoded 用于表单提交,表示数据以键值对的形式编码
        1. multipart/form-data 用于表单上传文件时,数据以多部分的形式发送,适合上传文件和其他数据
    • Cookie: 用于在客户端存储会话信息的一种方式

    • Authorization:用于提供身份验证信息,通常用于 API 访问

    • Connection: 如keep-alive ,指定连接的选项,例如是否保持连接

export class HttpHelper {
  baseUrl: string = '';
  sessionHelper = new SessionHelper();
  normalSession: rcp.Session = this.sessionHelper.createNormalSession();
  // User-Agent: 提供关于客户端软件的信息,例如浏览器类型和版本
  // Accept: 客户端可接受的内容类型 ,例如 application/json
  // Accept-Encoding: 客户端可接受的编码方式,如gzip,br

  // Content-Type: 它告诉服务 如何解析和处理请求
  //    1. application/json 表示请求或响应体中的数据是 JSON 格式
  //    2. application/x-www-form-urlencoded 用于表单提交,表示数据以键值对的形式编码
  //    3. multipart/form-data 用于表单上传文件时,数据以多部分的形式发送,适合上传文件和其他数据

  // Cookie: 用于在客户端存储会话信息的一种方式
  // Connection: 如keep-alive ,指定连接的选项,例如是否保持连接
  // Authorization:用于提供身份验证信息,通常用于 API 访问
  headers: rcp.RequestHeaders = {
    'authorization': 'token',
    'cookie': 'cookie',
    'user-agent': 'nzy手机',
    'accept': 'application/json',
    'content-type': 'application/x-www-form-urlencoded', // post时候使用 表单,告知服务器如何解析
    // 'content-type': 'application/json',// post的时候使用body
    // 'content-type': 'multipart/form-data'  // multipart
    'Connection': 'Keep-Alive',
    'accept-encoding': 'br,gzip', // 压缩方式
  };

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }
}
BaseResponse

跟服务端商量好,比如errorCode=0是正常流程,其他是否需要showToast看业务需要,自己配置就好

ts
 代码解读
复制代码
export interface BaseResponse<T> {
  errorCode: number 
  errorMsg: string
  data: T
}
get请求T

get请求不要传递到RequestContent ,他会跑到body里面,我们只能自己拼接到

async get<T>(path: string, params?: Record<string, RequestMapValue>): Promise<T> {
  // get 就不要放到params里面了,否则跑到body里面了,直接拼接到后面
  let newUrl = this.baseUrl + path
  if (params) {
    newUrl += '?' + Object.keys(params)
      .map(k => `${k}=${params[k]}`)
      .join('&')
  }
  let req = new rcp.Request(newUrl, 'GET', this.headers);
  let response = await this.normalSession.fetch(req)
  if (response.statusCode == 200) {
    let responseBase: T = response.toJSON() as T
    // 成功了
    return responseBase
  } else {
    return Promise.reject({ code: response.statusCode, message: 'http非200' })
  }
}
get请求BaseResponse 非0 就让他走到异常里面

这里把data内容包装成泛型,有时候需要非0的时候 需要toast errorMessage,可以做对应的逻辑处理,使用方错误的时候有三种情况

  • http code码非200
  • errorCode 非 0 ,这是跟后端对的业务,是否需要toast errorMessage
  • 业务处理的时候,crash了,
async get<T>(path: string, params?: Record<string, RequestMapValue>): Promise<T> {
  // get 就不要放到params里面了,否则跑到body里面了,直接拼接到后面
  let newUrl = this.baseUrl + path
  if (params) {
    newUrl += '?' + Object.keys(params)
      .map(k => `${k}=${params[k]}`)
      .join('&')
  }
  let req = new rcp.Request(newUrl, 'GET', this.headers);
  let response = await this.normalSession.fetch(req)
  if (response.statusCode == 200) {
    let responseBase: T = response.toJSON() as T
    // 成功了
    return responseBase
  } else {
    return Promise.reject({ netStatus: NetStatus.httpError, code: response.statusCode, message: 'http非200' })
  }
}

业务调用的时候

http.getBase<HarmonyData>("/project/list/1/json", { "cid": 249 })
  .then((data) => {
    Logger.json(data, 'response')
    // 非 0 就过去了
    this.message = JSON.stringify(data, null, 2)
  })
  .catch((err: NetError) => {
    Logger.error(err);
    if (err.netStatus) {
      // 证明是 http 错误
      if (err.netStatus == NetStatus.businessError) {
        //是否需要toast message
        promptAction.showToast({ message: err.message })
      }
    } else {
      // 代表业务有异常 ,也就是then里面代码crash了
    }
  })

POST 请求

post 请求分为三类,

  • JSON数据,也就是body里面是JSON格式
  • Form表单格式 body里是这样的password=xxx&username=xxx
  • Multipart格式,一般是包括文件,比如上传头像
POST JSON

这里因为我们不知道具体会给多少层,所以用了 value是ESObject 格式

async post<T>(path: string, params?: Record<string, ESObject>): Promise<T> {
  // 变更header中的 content-type 为 Body 格式
  this.headers['content-type'] = 'application/json'
  let req = new rcp.Request(`${this.baseUrl}${path}`, 'POST', this.headers, params);
  let response = await this.normalSession.fetch(req)
  if (response.statusCode == 200) {
    let responseBase: T = response?.toJSON() as T
    // 成功了
    return responseBase
  } else {
    return Promise.reject({ netStatus: NetStatus.httpError, code: response.statusCode, message: 'http非200' })
  }

}
使用
http.post<BaseResponse<HarmonyData>>(
  "/user/login",
  {
    'username': 'nzyandroid',
    'password': 'nzyandroid',
    'content': {
      'name': 'nzy',
      'age': 18
    }
  })
  .then((data) => {
    Logger.json(data, 'response')
    this.message = JSON.stringify(data, null, 2)
  })
  .catch((err: BusinessError) => {
    Logger.error(err);
  })

1

POST 表单
async postForm<T>(path: string, params?: Record<string, RequestMapValue>): Promise<T> {
  // 变更header中的 content-type 为 表单格式
  this.headers['content-type'] = 'application/x-www-form-urlencoded'
  const form = new rcp.Form(params as rcp.FormFields)
  let req = new rcp.Request(`${this.baseUrl}${path}`, 'POST', this.headers, form);
  let response = await this.normalSession.fetch(req)
  if (response.statusCode == 200) {
    let responseBase: T = response?.toJSON() as T
    // 成功了
    return responseBase
  } else {
    return Promise.reject({ netStatus: NetStatus.httpError, code: response.statusCode, message: 'http非200' })
  }
}
使用
http.postForm<BaseResponse<HarmonyData>>(
  "/user/login",
  {
    'username': 'nzyandroid',
    "password": 'nzyandroid'
  })
  .then((data) => {
    Logger.json(data, 'response')
    this.message = JSON.stringify(data, null, 2)
  }).catch((err: BusinessError) => {
  Logger.error(`Response err: Code is ${err.code}, message is ${err.message}`);
})

2

POST Multipart
async postMultipartForm<T>(path: string, params?: Record<string, RequestMapValue | MultipartFormFile>): Promise<T> {
  // 变更header中的 content-type 为 表单格式
  this.headers['content-type'] = 'multipart/form-data'
  const form = new rcp.MultipartForm(params as rcp.MultipartFormFields)
  let req = new rcp.Request(`${this.baseUrl}${path}`, 'POST', this.headers, form);
  let response = await this.normalSession.fetch(req)
  if (response.statusCode == 200) {
    let responseBase: T = response?.toJSON() as T
    // 成功了
    return responseBase
  } else {
    return Promise.reject({ netStatus: NetStatus.httpError, code: response.statusCode, message: 'http非200' })
  }
}
使用
http.postMultipartForm<Object>(
  "/user/login",
  {
    'name': 'nzy',
    'file': {
      remoteFileName: 'img1.jpg',
      contentOrPath: getContext(this).cacheDir + '/' + 'img1.jpg'
    }
  })
  .then((data) => {
    Logger.json(data, 'response')
    this.message = JSON.stringify(data, null, 2)
  })
  .catch((err: BusinessError) => {
    Logger.error(`Response err: Code is ${err.code}, message is ${err.message}`);
  })

3

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

2

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!
3


http://www.kler.cn/a/306483.html

相关文章:

  • 大数据新视界 -- 大数据大厂之 Impala 性能飞跃:动态分区调整的策略与方法(上)(21 / 30)
  • JFROG相关API
  • 【Python】爬虫通过验证码
  • AI写作(四)预训练语言模型:开启 AI 写作新时代(4/10)
  • https网站 请求http图片报错:net::ERR_SSL_PROTOCOL_ERROR
  • Pandas | 数据分析时将特定列转换为数字类型 float64 或 int64的方法
  • ChatGPT+2:修订初始AI安全性和超级智能假设
  • L298N电机驱动方案简介
  • JAVA:Nginx(轻量级的Web服务器、反向代理服务器)--(1)
  • JAVA学习-练习试用Java实现“串联所有单词的子串”
  • 物联网——USART协议
  • 揭开OpenAI草莓模型神秘面纱——重塑大语言模型的逻辑能力
  • np.argpartition 是 NumPy 库中的一个非常有用的函数,具体用法如下:
  • 力扣周赛:第415场周赛
  • 黑神话悟空+云技术,游戏新体验!
  • Using OpenAI API from Firebase Cloud Functions in flutter app
  • uniapp(H5)设置反向代理,设置成功后页面报错
  • 前端网络请求库:Axios
  • C++初阶学习——探索STL奥秘——vector的模拟实现
  • 20Kg载重30分钟续航多旋翼无人机技术详解
  • 微服务下功能权限与数据权限的设计与实现
  • 差分进化算法(DE算法)求解实例---旅行商问题 (TSP)
  • C语言自定义类型-联合与枚举
  • 无人机视角下落水救援检测数据集
  • Vue学习:props验证的一个小细节“Prop 名字格式”
  • 本专题大纲