• 鸿蒙极速入门(六)-加载请求状态管理-LoadState+观察者模式


    背景

    1、在ArkTS的架构中,没有明确的可管理的加载请求状态的脚手架,在进行网络请求过程中,无法简单的进行交互响应。

    2、参考Android中的LoadState写了一个简单的脚手架,以便在日常开发过程中,管理加载请求状态和UI交互。

    脚手架说明与源码

    1、状态机LoadState

    使用一个状态机,分别对应网络请求过程中的Loading(发起请求)、Loaded(请求成功)、LoadError(请求失败)状态,并支持链式调用:

    /**
    * 网络请求MVVM数据模型,由子类实现状态机管理,由方法实现回调监听
    */
    export abstract class LoadState {
    /**
    * loading函数,如果当前状态是Loading,则调用回调函数
    * @param callBack 回调函数
    * @returns this
    */
    loading(callBack?: () => void): this {
    if (this instanceof Loading) {
    callBack?.call(null);
    }
    return this;
    }
    /**
    * loaded函数,如果当前状态是Loaded,则调用回调函数
    * @param callBack 回调函数
    * @returns this
    */
    loaded(callBack?: (result: Loaded<any>) => void): this {
    if (this instanceof Loaded) {
    callBack?.call(null, this);
    }
    return this;
    }
    /**
    * loadError函数,如果当前状态是LoadError,则调用回调函数
    * @param callBack 回调函数
    * @returns this
    */
    loadError(callBack?: (error: LoadError) => void): this {
    if (this instanceof LoadError) {
    callBack?.call(null, this);
    }
    return this;
    }
    }
    /**
    * Loading类,继承自LoadState类
    */
    export class Loading extends LoadState {}
    /**
    * Loaded类,继承自LoadState类,包含一个result属性和一个data方法
    */
    export class Loaded extends LoadState {
    result?: T;
    constructor(data: T) {
    super();
    this.result = data;
    }
    data(): T | undefined {
    return this.result;
    }
    }
    /**
    * LoadError类,继承自LoadState类,包含code和message属性
    */
    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作为观察者实现类:

    /**
    * ValueNotifier类,包含_value、listeners属性和addListener、notifyListeners、value方法
    */
    export class ValueNotifier {
    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
  • 相关阅读:
    Go 1.19 发行说明(翻译)
    英特尔神经网络计算棒
    Python生成指定大小的文件
    Netty 基础详解
    SecureCRT -- 使用说明
    Fiddler抓包:下载、安装及使用
    Redis快速入门
    java基于springboot美食推荐管理系统附源码风格
    【ORACLE】ORA-00972:标识符过长
    Python图像处理丨图像的灰度线性变换
  • 原文地址:https://www.cnblogs.com/anywherego/p/17800794.html