HarmonyOS 鸿蒙Next 如何优雅的在网络框架中设置请求时的loading和请求返回时取消
如下,是封装的一个网络请求类
import { http } from '[@kit](/user/kit).NetworkKit'
import NetConstant from './NetConstant'
import { showToast } from '../utils/ToastUtil'
import { BaseResponse } from './BaseResponse'
import { LogUtil } from '../log/LogUtil'
import { LoadingDialog } from '../view/LoadingDialog'
const httpRequest = http.createHttp()
const loadingDialogController: CustomDialogController = new CustomDialogController({
builder: LoadingDialog({ loadingTips: "this.loadingTips" }),
autoCancel: true,
gridCount: 2
})
async function requestHttp<T>(url: string = "",
method: http.RequestMethod = http.RequestMethod.GET, data?: object): Promise<T> {
let requestUrl = NetConstant.BASE_URL + url
if (method === http.RequestMethod.GET) {
if (data && Object.keys(data).length) {
requestUrl += '?' + Object.keys(data).map(key => {
if (data[key]) {
return `${key}=${data[key]}`
}
return ''
}).join('&')
}
}
const token = AppStorage.get(NetConstant.ACCESS_TOKEN) as string
let headers: Record<string, Object> = {}
headers['Content-Type'] = 'application/json'
if (token.length > 0) {
headers['Authorization'] = 'Bearer ' + token
}
const config: http.HttpRequestOptions = {
header: headers,
method,
readTimeout: NetConstant.HTTP_READ_TIMEOUT,
extraData: method === http.RequestMethod.GET ? '' : data
}
try {
const res = await httpRequest.request(requestUrl, config)
if (res.responseCode === 401) {
showToast('token超时')
return Promise.reject(new Error('token 不存在或超时'))
} else if (res.responseCode === 404) {
showToast('请求地址不正确')
return Promise.reject(new Error('token 请求地址不正确'))
} else {
const result = JSON.parse(res.result as string) as BaseResponse<T>
if (result.code === 200 || result.code === 0) {
LogUtil.error(JSON.stringify(result.data))
LogUtil.info('转换前')
let finalResult: T = result.data as T
LogUtil.info('转换后')
return finalResult
} else {
showToast(result.msg)
return Promise.reject(new Error(result.msg))
}
}
} catch (err) {
showToast(err.message)
return Promise.reject(err)
} finally {
httpRequest.destroy()
}
}
export default class Request {
export
function
httpGet<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.GET, data)
}
export
function
httpPost<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>
(url, http.RequestMethod.POST, data)
}
export
function
httpPut<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.PUT, data)
}
export
function
httpDelete<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.DELETE, data)
}
}
[@Entry](/user/Entry)
[@Component](/user/Component)
export struct LoadingPage {
[@Prop](/user/Prop) flag: boolean;
build() {
Row() {
LoadingProgress().color(Color.White).width(50).height(50)
}
.height(this.flag ? '100%' : 0)
.width('100%')
.position({ x: 0, y: 0 })
.backgroundColor('#4D000000')
.justifyContent(FlexAlign.Center)
}
}
[@Component](/user/Component)
export struct HomePage {
[@State](/user/State) homePageBean: HomePageBean = new HomePageBean()
[@State](/user/State) coreAreaArrayOne: Array<CoreAreaInfo> = [new CoreAreaInfo()]
[@State](/user/State) coreAreaArrayTwo: Array<CoreAreaInfo> = [new CoreAreaInfo()]
[@State](/user/State) resHotAreaDTOList: ResHotAreaDTOList = new ResHotAreaDTOList()
[@State](/user/State) publicBenefitPageVOList: Array<PublicBenefitPageVO> = new Array()
[@State](/user/State) list: Array<BannerInfo> | Array<RightTop> = []
this
.showLoading = false
aboutToAppear(): void {
showLoading = true;
LoadingPage({ flag: this.showLoading });
httpGet<HomePageBean>(Constants.HOME_PAGE_MAIN_DATA).then(
homePageBean => {
showLoading = false
const data = JSON.stringify(homePageBean)
console.log('Michael 主页 JSON:', data)
this.coreAreaArrayOne = homePageBean.coreAreaListOne
this.coreAreaArrayTwo = homePageBean.coreAreaListTwo
this.resHotAreaDTOList = homePageBean.resHotAreaDTOList
this.publicBenefitPageVOList = homePageBean.publicBenefitPageVOList
this.list = homePageBean.bannerList
})
}
应用会有很多类似的这样的界面 如果每个界面都像上面那么写,势必很麻烦,那么如何在我封装的框架中进行请求的显示与隐藏的逻辑呢? 可提供你们的通用做法和demo
更多关于HarmonyOS 鸿蒙Next 如何优雅的在网络框架中设置请求时的loading和请求返回时取消的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
// CommonWindow.ets
import window from '@ohos.window';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';
import { entryName } from './MainPage';
export class CommonWindow {
private storage: LocalStorage | null = null;
private subWindow: window.Window | null = null;
private windowStage1: window.WindowStage | null = null
private context: common.UIAbilityContext | null = null;
private init() {
this.context = getContext(this) as common.UIAbilityContext;
let data: Data = { subWindowStage: null, storage: null };
this.context.eventHub.emit("createWindow", data);
this.windowStage1 = data.subWindowStage;
this.storage = data.storage;
console.log("aboutToAppear end createWindowStage");
this.context.eventHub.on("closeWindow", (data: Data) => {
this.destroySubWindow();
})
}
showWindow() {
this.init();
if (this.subWindow) {
console.log("subWindow is already exist");
return;
}
try {
if (!this.windowStage1) {
console.error("this.windowStage1 is null");
return;
}
this.windowStage1.createSubWindow('mySubWindow', (err: BusinessError, data) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to create the subWindow. Cause: ' + JSON.stringify(err));
return;
}
this.subWindow = (data as window.Window);
console.info('Succeeded in creating the subWindow. Data: ' + JSON.stringify(data));
if (!this.subWindow) {
console.info('Failed to load the content. Cause: windowClass is null');
} else {
let names: Array<'status' | 'navigation'> = [];
this.subWindow.setWindowSystemBarEnable(names);
this.subWindow.setWindowTouchable(true);
this.loadContent(entryName);
this.showSubWindow();
}
});
} catch (exception) {
console.error('Failed to create the window. Cause: ' + JSON.stringify(exception));
}
}
private showSubWindow() {
if (this.subWindow) {
this.subWindow.showWindow((err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
return;
}
console.info('Succeeded in showing the window.');
});
} else {
console.info('showSubWindow subWindow not created.');
}
}
private destroySubWindow() {
if (this.subWindow) {
this.subWindow.destroyWindow((err) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to destroy the window. Cause:' + JSON.stringify(err));
return;
}
this.subWindow = null
});
} else {
console.info('showSubWindow subWindow not created.');
}
}
private loadContent(path: string) {
if (this.subWindow) {
let that = this;
let para: Record<string, number> = { 'PropA': 66 };
that.storage = new LocalStorage(para);
if (that.storage != null && this.subWindow != null) {
that.storage.setOrCreate("windowObj", this.subWindow)
}
this.subWindow.loadContentByName(path, this.storage, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
return;
}
if (this.subWindow) {
this.subWindow.setWindowBackgroundColor('#cc000e03')
}
});
} else {
console.info('loadContent subWindow not created.');
}
}
}
export interface Data {
subWindowStage: window.WindowStage | null,
storage: LocalStorage | null
}
// MainPage.ets
import window from '@ohos.window';
export const entryName: string = 'loadingPage';
@Entry({ routeName: entryName, storage: LocalStorage.getShared() })
@Component
export struct MainPage {
@LocalStorageLink('PropA') var
number | undefined = 1;
private subWindow: window.Window | undefined;
build() {
Column() {
LoadingProgress().width(150)
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
// 页面生命周期:打开沉浸式
onPageShow() {
window.getLastWindow(getContext(this), (err, win) => {
// 获取当前窗口的属性
let prop: window.WindowProperties = win.getWindowProperties();
// 打印当前窗口属性
console.log(JSON.stringify(prop));
win.setWindowLayoutFullScreen(true)
})
}
// 页面生命周期:关闭沉浸式
onPageHide() {
window.getLastWindow(getContext(this), (err, win) => {
win.setWindowLayoutFullScreen(false)
})
}
aboutToAppear() {
this.varA = LocalStorage.getShared().get<number>("PropA");
this.subWindow = LocalStorage.getShared().get<window.Window>("windowObj");
}
}
EntryAbility.ets中
1、增加subWindowStage定义
private subWindowStage: window.WindowStage | undefined = undefined;
2、onCreate增加监听
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
const that: EntryAbility = this
this.context.eventHub.on("createWindow", (data: Data) => {
if (that.subWindowStage != undefined) {
data.subWindowStage = that.subWindowStage
} else {
hilog.info(0x0000, 'testTag', '%{public}s', 'that.subWindowStage == undefined');
}
})
}
3、onWindowStageCreate中增加赋值 this.subWindowStage = windowStage
使用:
public httpRequest(reqMethod: http.RequestMethod, url: string): Promise<Object> {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
let promise = httpRequest.request(url, {
method: reqMethod,
readTimeout: 10000,
connectTimeout: 10000
});
new CommonWindow().showWindow();
//Processes the data and returns.
return new Promise((resolve, reject) => {
promise.then((resp) => {
this.closeSubWindow()
if (resp.responseCode === http.ResponseCode.OK) {
//Obtains the returned data.
const respData:Object = typeof resp.result === 'string' ? JSON.parse(resp.result) : resp.result
resolve(respData)
} else {
httpRequest.destroy();
reject('error')
}
}).catch((err:BusinessError) => {
this.closeSubWindow()
httpRequest.destroy();
reject('error');
})
})
}
closeSubWindow() {
let context = getContext(this) as common.UIAbilityContext;
context.eventHub.emit("closeWindow", null);
}
更多关于HarmonyOS 鸿蒙Next 如何优雅的在网络框架中设置请求时的loading和请求返回时取消的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,要在网络框架中优雅地设置请求时的loading和请求返回时取消,可以遵循以下步骤:
-
定义状态管理:在数据层或ViewModel中定义请求状态,如
loading
、success
、error
等。 -
网络请求发起:在发起网络请求时,将状态设置为
loading
,并显示加载动画或提示。 -
请求取消机制:
- 使用
CancellationToken
或类似机制管理请求的生命周期。 - 在UI层或ViewModel层提供一个取消请求的接口,比如
cancelRequest()
。 - 在请求返回或用户触发取消操作时,调用
cancelRequest()
取消网络请求。
- 使用
-
请求返回处理:
- 当请求成功返回时,更新状态为
success
,并处理返回的数据。 - 若请求失败(包括取消),更新状态为
error
,并显示错误信息。 - 无论成功或失败,都需要将
loading
状态重置。
- 当请求成功返回时,更新状态为
-
UI层响应:根据数据层或ViewModel层的状态变化,动态显示或隐藏加载动画、成功提示或错误提示。
通过以上步骤,可以在HarmonyOS鸿蒙Next中优雅地管理网络请求的状态,确保请求时的loading显示和请求返回时的取消操作得以妥善处理。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html