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);
  })
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}`);
})
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}`);
  })

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

下面是鸿蒙的完整学习路线 ,展示如下:

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

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

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

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

鸿蒙面经

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

相关推荐
SUGERBOOM5 分钟前
华为eNSP使用详解
网络·华为
洁洁!30 分钟前
【计算机网络】数据链路层深度解析
网络·网络协议·计算机网络
Aomnitrix3 小时前
网络协议全景:Linux环境下的TCP/IP、UDP
linux·运维·网络·c++·网络协议·tcp/ip·运维开发
哲伦贼稳妥3 小时前
网络运维故障处理
运维·网络·经验分享·职场和发展
bite_joker_xue3 小时前
HCIA--实验十六:ACL通信实验(2)
网络
物联网菜鸟3 小时前
linux网络编程1
网络
无衣同学9 小时前
HCIP--<OSPF2>
网络
awonw10 小时前
[网络][CISCO]CISCO IOS升级
网络·ios
OH五星上将10 小时前
如何编译OpenHarmony SDK API
嵌入式硬件·移动开发·api·sdk·harmonyos·openharmony·鸿蒙开发
snow@li11 小时前
AI问答-HTTP:理解 Content-Disposition
网络·网络协议·http