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

鸿蒙Next网络请求和解析

在鸿蒙sdk9之前,ets语法基本与ts/js一致,属于弱语言类型,若你之前,用vue或其它前端框架,写过同项目的小程序,那么里面的逻辑代码部分(如网络请求等)可以直接复制粘贴进ets,稍作修改就可使用!

但在鸿蒙sdk10以后,ets强制使用静态类型,也就是变为类似java,kotlin这样的强语言类型,书写变量时必须指定变量类型,否则报错(当然一些基础变量如 number string等可以直接初始化为对应类型,免写变量类型)!另外,新的sdk已不再支持var关键字,统一使用let!

在这里插入图片描述

    //指定变量类型
    let a:number=0
    let b:string="Hello World"

    //基础变量或已知变量类型时,可免写变量类型
    let c=0
    let d="Hello World"

什么情况下必须指定变量类型呢?
以往我们在js中,使用JSON.parse可以将一个json字符串转为对象,并直接调用对象里的变量:

  let obj = JSON.parse("{\"id\":1,\"name\":\"刘德华\"}")
  console.log(obj.id + "," + obj.name)

但在最新鸿蒙sdk中,已不再支持这种写法,会报错“Use explicit types instead of “any”, “unknown””,必须指定变量类型:

在这里插入图片描述

以下这样才是对的:

  • 先生成json对于的class类:
export class Test{
  id: number=0
  name: string=""
}
  • 再解析json:
    let obj: Test = JSON.parse("{\"id\":1,\"name\":\"刘德华\"}")
    console.log(obj.id + "," + obj.name)

并且,它还支持泛型,这对于原安卓/java开发者来说,就再熟悉不过了,非常实用:

  getData<T>(json: string): BaseBean<T> {
    let result: BaseBean<T> = JSON.parse(json)
    return result
  }

  ...

  let test = this.getData<TestBean>(json)
  console.log("test>>" + test.code + "," + test.msg + "," + test.data.id + "," + test.data.name)

有了这个支持,那在书写网络请求框架方面,体验将非常棒,堪比原生!

下面我就把网络请求部分代码直接贴出,并写一个简单的请求示例:

请求工具类request.ets:

import { http } from '@kit.NetworkKit';
import { BaseResult } from './bean/BaseResult';
import { RequestError } from './bean/RequestError';

function buildHeader(): Map<string, object> {
  let header: Map<string, object> = new Map<string, object>()
  header["Content-Type"] = "application/json"
  return header
}

export function get<T>(url: string): Promise<T> {
  return req<T>(http.RequestMethod.GET, url, undefined)
}

export function post<T>(url: string, params?: Map<string, object>): Promise<T> {
  return req<T>(http.RequestMethod.POST, url, params)
}

async function req<T>(method: http.RequestMethod, url: string, params?: Map<string, object>) {
  //每一个httpRequest对应一个http请求任务,不可复用
  let httpRequest = http.createHttp()
  let header = buildHeader()
  let paramsStr = JSON.stringify(params)
  return new Promise((resolve: (value: T) => void, reject: (reason?: RequestError) => void) => {
    httpRequest.request(url, {
      method: method,
      header: header,
      extraData: paramsStr,
      connectTimeout: 30000, // 可选,默认为60s
      readTimeout: 30000, // 可选,默认为60s
    }, (err, data) => {
      if (!err) {
        if (data.responseCode == 200) {
          let response = data.result.toString()
          let res: BaseResult<T> = JSON.parse(response)
          if (res.errorCode == 0) {
            resolve(res.data)
          } else {
            reject(new RequestError(res.errorCode, res.errorMsg))
          }
        } else {
          reject(new RequestError(data.responseCode, ""))
        }
      } else {
        reject(new RequestError(-1, JSON.stringify(err)))
      }
    })
  })
}

BaseResult:

export interface BaseResult<T> {
  errorCode: 0,
  errorMsg: string,
  data: T
}

RequestError:

export class RequestError {
  errorCode: number = 0
  errorMsg: string = ""

  constructor(errorCode: number, errorMsg: string) {
    this.errorCode = errorCode
    this.errorMsg = errorMsg
  }
}

每个模块对应一个Api请求类:

TestApi:

import { get, post } from '../request'
import { IndexModel } from './IndexModel'
import { LoginModel } from './LoginModel'

export default class TestApi {
  public static login(username: string, password: string): Promise<LoginModel> {
    let param: Map<string, object> = new Map<string, object>()
    param["username"] = username
    param["password"] = password
    return post("https://www.wanandroid.com/user/login", param)
  }

  public static getIndex(): Promise<IndexModel> {
    return get("https://www.wanandroid.com/article/list/1/json")
  }

}

json对象:

export interface LoginModel {
  id: number
  username: string
}
export interface IndexModel {
  curPage: number
  datas: Array<ItemModel>
}

export interface ItemModel {
  adminAdd: boolean;
  apkLink: string;
  audit: number;
  author: string;
  ...
}

注意,我这里对象类使用的是interface,而非class,两者的区别,可以自行百度一下,这里只说一点,interface不用初始化变量,而class中的变量必须初始化,否则报错!

请求示例:

    //登录(由于随便写的用户名和密码,报错是必然的,这里仅演示post请求)
    TestApi.login("liudehua", "123456").then(data => {
      if (data) {
        console.log("登录成功:" + data.username)
      }
    }).catch((error: RequestError) => {
      console.log("登录error:" + error.errorCode + "," + error.errorMsg)
    })
    
    //获取首页数据
    TestApi.getIndex().then(data => {
      if (data) {
        console.log("获取首页数据成功:" + data.curPage + "," + data.datas.length)
      }
    }).catch((error: RequestError) => {
      console.log("获取首页数据error:" + error.errorCode + "," + error.errorMsg)
    })

返回结果:

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述


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

相关文章:

  • go并发设计模式runner模式
  • 数据结构实训——查找
  • TypeScript和JavaScript区别详解
  • 在Java中使用Apache POI导入导出Excel(六)
  • Qt,如何从零开始入门!
  • Ubuntu Linux操作系统
  • node.js基础学习-crypto模块-加密解密(九)
  • Java项目实战II基于微信小程序的亿家旺生鲜云订单零售系统的设计与实现(开发文档+数据库+源码)
  • [代码随想录06]哈希表的使用,有效字母异位词,两数组交集,快乐数,两数之和
  • 分层图最短路
  • BGP通过route-policy路由策略调用ip-prefix网络前缀实现负载均衡与可靠性之AS-path属性
  • ES6中,Set和Map的区别
  • 对载入的3dtiles进行旋转、平移和缩放变换。
  • 解决git clone与git push出现的若干问题:Failed to connect to github.com port 443: Timed out
  • tauri使用github action打包编译多个平台arm架构和inter架构包踩坑记录
  • 2024免费天气接口(无废话版)
  • 数据增强方法
  • 轻量级探针 Beszel 监控 VPS / NAS 历史数据以及 Docker 统计数据
  • openharmony 下用jailhouse 虚拟化 rtos 技术方案
  • Java 在未来市场的需求风云
  • QT工程,它该怎么学?
  • ChemReasoner——基于量子化学与大语言模型(LLM) 发现最佳催化剂的框架并提高催化剂发现的效率
  • 长安汽车嵌入式面试题及参考答案
  • 2024信创数据库TOP30之华为Gauss DB
  • SCAU期末笔记 - 数据库系统概念
  • 【小白学机器学习41】如何从正态分布的总体中去抽样?比较不同的取样方差的差别