HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)


文章目录

  • 系列文章目录
  • 前言
  • 一、实现设计
  • 二、代码实现
    • 1.http请求工具类request.ets
    • 2.token持久化存取
    • 3.页面使用


前言

HarmonyOS Next(基于API11)封装一个http请求工具类,自动拦截token失效跳转登录页,以及token持久化存取方案。


一、实现设计

  • 对于接口请求我们最关心两个东西,一个是请求参数另一个是接收服务器返回的数据

(1)请求参数最常设置的有:

请求链接url、请求方式method(post,get等)、请求参数data、请求数据类型Content-Type、登录凭证token

其中token可从本地持久化读取无需传入,剩下四个可设计为动态传参

//接口入参数据类型
interface RequestParams {url: string //请求链接method?: http.RequestMethod //请求方式data?: Object //请求额外数据headerContentType?: string //请求数据类型
}

(2)返回数据一般是个对象 常见固定字段有:

code:状态码 ,message:接口响应说明 ,data:返回数据

故接口返回数据类型可定义为:

//接口请求返回数据类型
interface ResponseResult {code: number //状态码message: string //处理信息data: Object | null //返回数据
}

ps:根据实际需要也可按需添加字段

对于返回数据code状态码一般定义:
1、200为请求成功
2、401 token失效(无效或缺失)
3、其他情况归为请求失败

所以对于接口返回数据可根据code值分三种情况处理例如:

if(code==200){//请求成功//返回数据
}
else if(code==401){//token失效//拦截跳转到登录页router.replaceUrl({url: "/pages/login"})
}
else{//请求失败}

ps:当然状态码也可根据实际定义修改

  • Token持久化存储
    为了配合登录方案实现,方便在EntryAbility使用token,我们这里选择了Preferences作为存储方案。

最后,熟悉web开发的同学都知道web项目中习惯把接口定义放置在api文件夹下统一管理,然后在页面引入使用,再此沿用该开发习惯,方便后期维护。

二、代码实现

目录结构:
在这里插入图片描述

1.http请求工具类request.ets

封装一个http请求工具类文件,默认导出一个请求函数返回Promise(接口返回数据)

utils/request.ets

import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';
import promptAction from '@ohos.promptAction'
import { getToken } from './index'
import router from '@ohos.router';//baseURL接口域名
const BASEURL: string = "https://xxxxxxx.com"
//登录页路由
const LOGINPAGEURL = 'pages/common/login'//接口入参数据接口
interface RequestParams {url: stringmethod?: http.RequestMethoddata?: ObjectheaderContentType?: string
}//接口请求返回数据类
class ResponseResult {code: number //状态码message: string //处理信息data: Object | null //返回数据constructor(code?: number, message?: string, data?: Object | null | undefined) {this.code = code ?? 0this.message = message ?? ''this.data = data ?? null}
}/**** @param params:接口请求参数(object类型)* {*  url :请求连接*  method :请求方法*  data :请求数据*  headerContentType :请求头发送的数据格式* }* @returns Promise<ResponseResult>*/
export default function request(params: RequestParams): Promise<ResponseResult> {return new Promise(async (resolve: (res: ResponseResult) => void, reject: (res: ResponseResult | string | BusinessError | http.HttpResponse) => void) => {//请求头contentTypelet contentType: string = params.headerContentType || 'application/json' //默认提交数据类型为application/json//请求数据datalet requestData: Object | undefined = params.data;//application/x-www-form-urlencoded类型参数处理成key&value形式if (contentType === 'application/x-www-form-urlencoded') {if (typeof params.data === 'object') {requestData = Object.entries(requestData as object).reduce((prev: string, cur: Array<Object>) => {return (prev && `${prev}&`) + `${cur[0]}=${cur[1]}`}, '')}}//从本地存储获取tokenlet token: string = await getToken()let httpRequest = http.createHttp();httpRequest.request(BASEURL + params.url, {method: params.method ?? http.RequestMethod.GET, //默认get方法header: {'Content-Type': contentType,token},extraData: requestData,readTimeout: 30000,connectTimeout: 30000}, (err: BusinessError, data: http.HttpResponse) => {if (!err) {//请求成功if (data.responseCode === 200) {let res: ResponseResult = JSON.parse(`${data.result}`);let response = new ResponseResult(res.code, res.message, res.data)//状态码code=200表示请求成功,状态码可根据实际接口文档修改if (res.code === 200) {resolve(response);}//状态码code=401表示token失效,状态码可根据实际接口文档修改else if (res.code === 401) { //跳转登录页router.clear() //清空历史页面//跳转到登录页router.replaceUrl({url: LOGINPAGEURL})}//其他情况接口异常else {showToast(response.message)reject(response);}}//请求失败else {showToast()reject(data)}}//请求失败else {showToast(err.message)reject(err)}// 取消订阅HTTP响应头事件httpRequest.off('headersReceive');// 当该请求使用完毕时,主动销毁该JavaScript Object。httpRequest.destroy();})})
}//弹窗提示
const showToast = (message?: string) => {promptAction.showToast({message: message || '请求出错',duration: 2000})
}

说明:
(1)定义了接口前缀(域名+端口号?+通用匹配符?) BASEURL:可根据实际修改
(2)定义了登录页面路由 LOGINPAGEURL token失效跳转使用 :可根据实际修改
(3)函数request入参是个对象,包含如下属性

{url :请求连接method ?:请求方法data ?:请求数据headerContentType? :请求头发送的数据格式}

method不传默认get方式,headerContentType 不传默认application/json
当contetn-type为 “application/x-www-form-urlencoded” , data请求参数 自动处理成key&value形式

(4)请求结果返回Promise

  {code: number //状态码message: string //处理信息data: Object | null //返回数据
}

当code=200,promise返回接口数据
当code=401 token失效自动跳转登录页,
当code其他值表示请求失败,showToast显示接口message字段文字

(5)请求头默认添加token数据,从本地存储读取

2.token持久化存取

(1)entryability/EntryAbility.ets

import dataPreferences from '@ohos.data.preferences';
....
....
....onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {globalThis.getPreferences = () => {let preferences: Promise<dataPreferences.Preferences> = dataPreferences.getPreferences(this.context, "appStore")return preferences}}

EntryAbility. onCreate周期函数内给全局变量globalThis添加getPreferences 属性方法,方便快速获取Preferences实例 ,添加到globalThis是为了后续页面开发或者工具类使用Preferences

(2)utils/index.ets 工具类

import dataPreferences from '@ohos.data.preferences';
//获取token
export const getToken: Function = async () => {try {let preferences: dataPreferences.Preferences = await globalThis.getPreferences()return preferences.getSync('token', '')}catch (e) {}return ''
}//设置token并本地持久化存储
export const setToken: Function = async (value: string) => {try {let preferences: dataPreferences.Preferences = await globalThis.getPreferences()preferences.putSync('token', encodeURIComponent(value))await preferences.flush()}catch (e) {console.log(JSON.stringify(e), 'e')}
}

在工具类index.ets封装2个方法(getToken,setToken),分别为获取token值和设置token值,其中setToken在登录成功获取到token值时候调用存入本地持久化

3.页面使用

在这里插入图片描述
新建api文件夹、新建与页面同名的ets文件写入api定义
api/home.ets


import http from '@ohos.net.http'
import request from '../utils/request'class params{storeId:string=''
}
//获取首页数据
export function getHomeData(data:params){return request({url:"/api/store/home",method:http.RequestMethod.POST, //不传默认GETdata,headerContentType:'application/x-www-form-urlencoded' //不传默认application/json})
}//其他接口
export function xxxxx(data:params){return request({url:"xxxxxxxx",data,})
}
......
......
......

页面引入
pages/Home.ets

import {getHomeData} from "../api/home"
@Entry
@Component
struct Home{aboutToAppear(): void {getHomeData({storeId:'17815455885'}).then(res=>{console.log(JSON.stringify(res),'接口返回数据')}}
}

运行结果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/26201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows上修改Podman的镜像配置源加速

目录 前言解决办法1. 打开window的Powershell 2. 修改registries.conf3. 重启podman即可 扩展内容1. 国内镜像源地址2. 阿里加速地址 前言 今天在电脑上准备通过podman安装mysql&#xff0c;结果执行安装命令后&#xff0c;网络不通没法下载镜像。 解决办法 将默认镜像源修改…

释放创意潜力:AI写作助手如何助力内容创作?

内容为王&#xff0c;在内容创作的世界中尤为重要。然而&#xff0c;面对写作时常常感到无从下手&#xff1a;有时缺乏灵感&#xff0c;有时难以表达清楚自己的想法。AI写作助手的出现&#xff0c;为这些问题提供了创新的解决方案&#xff0c;极大地改变了内容创作的过程。 今…

C++: shared_ptr是线程安全的吗

导读 C面试中有时会有这样一个问题&#xff0c;shared_ptr是线程安全的吗&#xff1f;对此问题&#xff0c;我们需要从三个并发场景进行考虑&#xff0c;拷贝shared_ptr的安全性、对shared_ptr赋值的安全性和读写shared_ptr指向内存区域的安全性。 对于以上问题&#xff0c;首…

奥特曼28亿「投资帝国」曝光!不要OpenAI股份,当CEO最不赚钱

Sam Altman十几年来建立的庞大投资帝国&#xff0c;让我们终于理解了他为什么可以不要OpenAI的股权。 内容提要 作为一家曾经的小型非盈利组织&#xff0c;OpenAI以创纪录的速度迅速成长为估值860亿美元的独角兽。 虽然这大多归功于Sam Altman和微软达成的商业合作&#xff…

超强 BAAS 神器:支持自动生成API、对象存储、静态托管,云函数!

想象一下&#xff0c;你是一名开发者&#xff0c;你有一种强大的神器&#xff0c;可以让你摆脱繁琐的服务搭建和接口开发&#xff0c;免费使用众多第三方认证服务、对象存储、云函数和静态部署。这就是MemFire Cloud&#xff01; MemFire Cloud是懒人开发者的福音&#xff0c;一…

开源VisualFbeditor中文版,vb7 IDE,VB6升级64位跨平台开发安卓APP,Linux程序

吴涛老矣&#xff0c;社区苦无64位易语言&#xff0c;用注入DLL增强菜单&#xff0c;做成VS一样的界面 终归是治标不治本&#xff0c;一来会报毒&#xff0c;二来闭源20年没更新了 开源的VB7&#xff0c;欢迎易语言的铁粉进群&#xff1a;1032313876 【Freebasic编程语言】编绎…

Transformer论文解读

目录 写在前面 一、Transformer要解决的问题 1.长距离依赖问题 2.序列处理瓶颈 二、整体结构 三、自注意力机制 1.Scaled Dot-Product Attention 2.Multi-Head Attention 四、Position-wise Feed-Forward Networks&#xff08;FFN&#xff09; 五、位置编码 六、总结…

数组双指针经典习题

合并两个有序数组 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int p1m-1,p2n-1;int p3nums1.length-1;while(p1>0&&p2>0){//放完一个数组if(nums1[p1]>nums2[p2]){nums1[p3--]nums1[p1];p1--;}else{nums1[p3--]nums2[p2];p…

iOS调整collectionViewCell顺序

效果图 原理 就是设置collectionView调整顺序的代理方法&#xff0c;这里要注意一点 调整过代理方法之后&#xff0c;一定要修改数据源&#xff0c;否则导致错乱。 还有就是在collectionView上面添加一个长按手势&#xff0c;在长按手势的不同阶段&#xff0c;调用collectionV…

第18篇 Intel FPGA Monitor Program的使用<一>

Q&#xff1a;Intel FPGA Monitor Program开发工具可以支持Terasic的FPGA开发板使用吗&#xff1f; A&#xff1a;Intel FPGA Monitor Program 是Intel提供的适用于 ARM* Cortex*-A9 处理器和 Nios II 处理器的完整软件开发环境&#xff0c;它包括编译工具以及完整的调试功能&…

全国电力变压器数据

全国共10330个电力变压器 属性部分并不是很全&#xff0c;比如说一次电压&#xff0c;二次电压只有200条是全的 不过以我做电力采集时的经验&#xff0c;其实变压器的数量和位置是最难采集的数据&#xff0c;反而电压、电流、功率这些专业数据可以直接找设备台账补充或利用移动…

log4j日志打印导致OOM问题

一、背景 某天压测&#xff0c;QPS压到一定值后机器就开始重启&#xff0c;出现OOM&#xff0c;好在线上机器配置了启动参数-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/**/**heapdump.hprof。将dump文件下载到本地&#xff0c;打开Java sdk bin目录下的jvisualvm工具&a…

35、matlab设置字体、查看工具包版本、窗口默认布局和程序发布

1、matlab设置字体 1&#xff09;找到预设并点击预设 2&#xff09;设置流程&#xff1a;字体——>自定义——>编辑器——>选择字体及格式——>确定 如图序号所示 2、matlab查看工具包版本&#xff1a;ver命令 1&#xff09;命令行窗口输入命令 即可查看工具包…

如何使用前端表格控件实现数据更新?

前言 小编之前分享过一篇文章叫《如何使用前端表格控件实现多数据源整合&#xff1f;》。今天&#xff0c;继续为大家介绍如何使用前端表格控件来更新已连接的数据源信息。 环境准备 SpreadJS在线表格编辑器&#xff1a; SpreadJS 前端表格控件新版本新增了一款报表插件&am…

Python altair库:轻松打造高颜值数据可视化图表

更多Python学习内容&#xff1a;ipengtao.com Altair是一个基于Vega和Vega-Lite构建的Python数据可视化库。它提供了一个简单且直观的API&#xff0c;能够生成具有交互性的统计图表。Altair的设计理念是通过声明式的语法定义图表&#xff0c;从而简化了复杂图表的创建过程。本文…

VUE脚手架更新

用vue命令创建命令时发现提示需要更新vue-cli 卸载原脚手架 npm uninstall vue-cli -g 升级 npm install -g vue/cli 检查版本 vue -V 注意是大写的v

【PowerDesigner】创建和管理CDM之新建和使用域

目录 &#x1f30a;1. PowerDesigner简介 &#x1f30d;1.1 常用模型文件 &#x1f30d;1.2 PowerDesigner使用环境 &#x1f30a;2. 创建和管理CDM &#x1f30d;​​​​​​2.1 新建CDM &#x1f30d;2.2 新建和使用域 &#x1f30a;3. 研究心得 &#x1f30a;1. Pow…

pxe自动装机:

pxe自动装机&#xff1a; 服务端和客户端 pxe c/s模式&#xff0c;允许客户端通过网络从远程服务器&#xff08;服务端&#xff09;下载引导镜像&#xff0c;加载安装文件&#xff0c;实现自动化安装操作系统。 无人值守 无人值守&#xff0c;就是安装选项不需要人为干预&am…

最全面又最浅显易懂的Langchain快速上手教程(下)

最全面又最浅显易懂的Langchain快速上手教程&#xff08;下&#xff09; 三. 深入Langchain 1. 架构设计 从上文知道Langchain在架构上使用了从抽象、到具体、再到整合适配的三层架构&#xff0c;这种一层一层逐渐具体的设计最大可能性的保证了架构的可扩展性和维护性。同时…

【Vue】封装api接口 - 图片验证码接口

**1.目标&#xff1a;**将请求封装成方法&#xff0c;统一存放到 api 模块&#xff0c;与页面分离 2.原因&#xff1a;以前的模式 页面中充斥着请求代码 可阅读性不高 相同的请求没有复用请求没有统一管理 3.期望&#xff1a; 请求与页面逻辑分离相同的请求可以直接复用请求…