背景
1、在ArkTS的架构中,没有明确的可管理的加载请求状态的脚手架,在进行网络请求过程中,无法简单的进行交互响应。
2、参考Android中的LoadState写了一个简单的脚手架,以便在日常开发过程中,管理加载请求状态和UI交互。
脚手架说明与源码
1、状态机LoadState
使用一个状态机,分别对应网络请求过程中的Loading(发起请求)、Loaded(请求成功)、LoadError(请求失败)状态,并支持链式调用:
| |
| |
| |
| export abstract class LoadState { |
| |
| |
| |
| |
| |
| loading(callBack?: () => void): this { |
| if (this instanceof Loading) { |
| callBack?.call(null); |
| } |
| return this; |
| } |
| |
| |
| |
| |
| |
| |
| loaded(callBack?: (result: Loaded<any>) => void): this { |
| if (this instanceof Loaded) { |
| callBack?.call(null, this); |
| } |
| return this; |
| } |
| |
| |
| |
| |
| |
| |
| loadError(callBack?: (error: LoadError) => void): this { |
| if (this instanceof LoadError) { |
| callBack?.call(null, this); |
| } |
| return this; |
| } |
| } |
| |
| |
| |
| |
| export class Loading extends LoadState {} |
| |
| |
| |
| |
| export class Loaded<T> extends LoadState { |
| result?: T; |
| |
| constructor(data: T) { |
| super(); |
| this.result = data; |
| } |
| |
| data(): T | undefined { |
| return this.result; |
| } |
| } |
| |
| |
| |
| |
| export class LoadError extends LoadState { |
| code?: number; |
| message?: string; |
| |
| constructor(code: number, message: string) { |
| super(); |
| this.code = code; |
| this.message = message; |
| } |
| } |
| |
2、观察者模式
ArtTS没有提供开箱即用的观察者模式框架,也无法直接使用RxJS框架,所以自己手写一个简单的ValueNotifier作为观察者实现类:
| |
| |
| |
| export class ValueNotifier<T> { |
| private _value: T; |
| listeners: Array<() => void> = []; |
| |
| constructor(value: T) { |
| this._value = value; |
| } |
| |
| get value(): T { |
| return this._value; |
| } |
| |
| set value(value: T) { |
| this._value = value; |
| this.notifyListeners(); |
| } |
| |
| addListener(listener: () => void) { |
| this.listeners.push(listener); |
| } |
| |
| notifyListeners() { |
| for (let listener of this.listeners) { |
| listener(); |
| } |
| } |
| } |
使用示例
以获取一个车辆详情的场景来模拟网络请求和数据处理
1、ViewModel
| import { Loaded, LoadError, Loading, LoadState, ValueNotifier } from './LoadState'; |
| |
| export class VehicleViewModel { |
| lsVehicleDetail: ValueNotifier<LoadState | null>; |
| |
| constructor() { |
| this.lsVehicleDetail = new ValueNotifier<LoadState | null>(null); |
| } |
| |
| |
| async getVehicleDetail() { |
| |
| this.lsVehicleDetail.value = new Loading(); |
| |
| await new Promise(resolve => setTimeout(resolve, 3000)); |
| |
| |
| this.lsVehicleDetail.value = new Loaded("aa"); |
| |
| await new Promise(resolve => setTimeout(resolve, 3000)); |
| |
| |
| this.lsVehicleDetail.value = new LoadError(123, "error"); |
| } |
| } |
2、页面处理
| @Component |
| export struct VehicleComponent { |
| private vm: VehicleViewModel = new VehicleViewModel(); |
| |
| aboutToAppear() { |
| |
| this.vm.lsVehicleDetail.addListener(() => { |
| this.vm.lsVehicleDetail.value?.loading(() => { |
| |
| console.log(`hello1:start Loading`); |
| }).loaded((result) => { |
| let data = result?.data() as String |
| console.log(`hello2:${result} - ${data}`); |
| }).loadError((error) => { |
| console.log(`hello3:${error?.code} - ${error?.message}`); |
| }); |
| }); |
| } |
| } |
3、日志打印结果
| hello1:start Loading |
| hello2:[object Object] - aa |
| hello3:123 - error |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)