鸿蒙Next网络请求和剖析

打印 上一主题 下一主题

主题 801|帖子 801|积分 2403

在鸿蒙sdk9之前,ets语法基本与ts/js一致,属于弱语言类型,若你之前,用vue或其它前端框架,写过同项目的小步伐,那么里面的逻辑代码部分(如网络请求等)可以直接复制粘贴进ets,稍作修改就可使用!
但在鸿蒙sdk10以后,ets逼迫使用静态类型,也就是变为类似java,kotlin如许的强语言类型,誊写变量时必须指定变量类型,否则报错(当然一些基础变量如 number string等可以直接初始化为对应类型,免写变量类型)!另外,新的sdk已不再支持var关键字,统一使用let!

  1.     //指定变量类型
  2.     let a:number=0
  3.     let b:string="Hello World"
  4.     //基础变量或已知变量类型时,可免写变量类型
  5.     let c=0
  6.     let d="Hello World"
复制代码
什么环境下必须指定变量类型呢?
以往我们在js中,使用JSON.parse可以将一个json字符串转为对象,并直接调用对象里的变量:
  1.   let obj = JSON.parse("{"id":1,"name":"刘德华"}")
  2.   console.log(obj.id + "," + obj.name)
复制代码
但在最新鸿蒙sdk中,已不再支持这种写法,会报错“Use explicit types instead of “any”, “unknown””,必须指定变量类型:

以下如许才是对的:


  • 先生成json对于的class类:
  1. export class Test{
  2.   id: number=0
  3.   name: string=""
  4. }
复制代码


  • 再剖析json:
  1.     let obj: Test = JSON.parse("{"id":1,"name":"刘德华"}")
  2.     console.log(obj.id + "," + obj.name)
复制代码
而且,它还支持泛型,这对于原安卓/java开发者来说,就再熟悉不过了,非常实用:
  1.   getData<T>(json: string): BaseBean<T> {
  2.     let result: BaseBean<T> = JSON.parse(json)
  3.     return result
  4.   }
  5.   ...
  6.   let test = this.getData<TestBean>(json)
  7.   console.log("test>>" + test.code + "," + test.msg + "," + test.data.id + "," + test.data.name)
复制代码
有了这个支持,那在誊写网络请求框架方面,体验将非常棒,堪比原生!
下面我就把网络请求部分代码直接贴出,并写一个简单的请求示例:
请求工具类request.ets:
  1. import { http } from '@kit.NetworkKit';
  2. import { BaseResult } from './bean/BaseResult';
  3. import { RequestError } from './bean/RequestError';
  4. function buildHeader(): Map<string, object> {
  5.   let header: Map<string, object> = new Map<string, object>()
  6.   header["Content-Type"] = "application/json"
  7.   return header
  8. }
  9. export function get<T>(url: string): Promise<T> {
  10.   return req<T>(http.RequestMethod.GET, url, undefined)
  11. }
  12. export function post<T>(url: string, params?: Map<string, object>): Promise<T> {
  13.   return req<T>(http.RequestMethod.POST, url, params)
  14. }
  15. async function req<T>(method: http.RequestMethod, url: string, params?: Map<string, object>) {
  16.   //每一个httpRequest对应一个http请求任务,不可复用
  17.   let httpRequest = http.createHttp()
  18.   let header = buildHeader()
  19.   let paramsStr = JSON.stringify(params)
  20.   return new Promise((resolve: (value: T) => void, reject: (reason?: RequestError) => void) => {
  21.     httpRequest.request(url, {
  22.       method: method,
  23.       header: header,
  24.       extraData: paramsStr,
  25.       connectTimeout: 30000, // 可选,默认为60s
  26.       readTimeout: 30000, // 可选,默认为60s
  27.     }, (err, data) => {
  28.       if (!err) {
  29.         if (data.responseCode == 200) {
  30.           let response = data.result.toString()
  31.           let res: BaseResult<T> = JSON.parse(response)
  32.           if (res.errorCode == 0) {
  33.             resolve(res.data)
  34.           } else {
  35.             reject(new RequestError(res.errorCode, res.errorMsg))
  36.           }
  37.         } else {
  38.           reject(new RequestError(data.responseCode, ""))
  39.         }
  40.       } else {
  41.         reject(new RequestError(-1, JSON.stringify(err)))
  42.       }
  43.     })
  44.   })
  45. }
复制代码
BaseResult:
  1. export interface BaseResult<T> {
  2.   errorCode: 0,
  3.   errorMsg: string,
  4.   data: T
  5. }
复制代码
RequestError:
  1. export class RequestError {
  2.   errorCode: number = 0
  3.   errorMsg: string = ""
  4.   constructor(errorCode: number, errorMsg: string) {
  5.     this.errorCode = errorCode
  6.     this.errorMsg = errorMsg
  7.   }
  8. }
复制代码
每个模块对应一个Api请求类:
TestApi:
  1. import { get, post } from '../request'
  2. import { IndexModel } from './IndexModel'
  3. import { LoginModel } from './LoginModel'
  4. export default class TestApi {
  5.   public static login(username: string, password: string): Promise<LoginModel> {
  6.     let param: Map<string, object> = new Map<string, object>()
  7.     param["username"] = username
  8.     param["password"] = password
  9.     return post("https://www.wanandroid.com/user/login", param)
  10.   }
  11.   public static getIndex(): Promise<IndexModel> {
  12.     return get("https://www.wanandroid.com/article/list/1/json")
  13.   }
  14. }
复制代码
json对象:
  1. export interface LoginModel {
  2.   id: number
  3.   username: string
  4. }
复制代码
  1. export interface IndexModel {
  2.   curPage: number
  3.   datas: Array<ItemModel>
  4. }
  5. export interface ItemModel {
  6.   adminAdd: boolean;
  7.   apkLink: string;
  8.   audit: number;
  9.   author: string;
  10.   ...
  11. }
复制代码
注意,我这里对象类使用的是interface,而非class,两者的区别,可以自行百度一下,这里只说一点,interface不消初始化变量,而class中的变量必须初始化,否则报错!
请求示例:
  1.     //登录(由于随便写的用户名和密码,报错是必然的,这里仅演示post请求)
  2.     TestApi.login("liudehua", "123456").then(data => {
  3.       if (data) {
  4.         console.log("登录成功:" + data.username)
  5.       }
  6.     }).catch((error: RequestError) => {
  7.       console.log("登录error:" + error.errorCode + "," + error.errorMsg)
  8.     })
  9.    
  10.     //获取首页数据
  11.     TestApi.getIndex().then(data => {
  12.       if (data) {
  13.         console.log("获取首页数据成功:" + data.curPage + "," + data.datas.length)
  14.       }
  15.     }).catch((error: RequestError) => {
  16.       console.log("获取首页数据error:" + error.errorCode + "," + error.errorMsg)
  17.     })
复制代码
返回结果:

知心小提示:json对象的生成,如果变量全部手敲的话,那就太费时费力了,在早期DevEcoSutdio中有一个JsonToTS的插件可以使用,将json转为ts类型,但新版本中这个插件不兼容了,需要等候作者更新!此时,可以在Vscode中,安装一个json to ts的插件,复制json代码,然后使用ctrl+shift+v快捷键,便直接生成ts代码了,还是很方便的!



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表