Core Technologies of HarmonyOS ## Sports Development ## Remote Communication Kit (Remote Communication Services)
In the previous articles, we have introduced in detail how to package a complete RCP network library and explored its core functions and advanced features. In this part, we will demonstrate how to use this network library in HarmonyOS sports projects to implement specific network request functions.
Preface
In HarmonyOS sports projects, network requests are a key part of implementing functionality. Whether it is obtaining sports data, synchronizing user information, or loading sports video resources, a stable, efficient, and easy-to-use network library is required. In this part, we will show how to use the packaged RCP network library to achieve these functions through practical code examples.
I. Packaging Exception Handling
In actual development, exception handling is an indispensable part of network requests. By defining custom exception classes, we can better manage various errors that may occur in network requests.
(I) Custom Exception Class
A ApiException
class has been defined to encapsulate error information in API requests.
export class ApiException extends Error {
apiCode?: number;
apiMessage?: string;
constructor(apiCode?: number, apiMessage?: string) {
super();
this.name = "ApiException";
this.apiCode = apiCode;
this.apiMessage = apiMessage;
}
}
Core Points Analysis:
-
Custom Properties:
apiCode
andapiMessage
are used to store the error code and error message returned by the API. - Constructor: The constructor initializes the exception object and sets the error code and error message.
II. Packaging Network Requests
To simplify the implementation of network requests, you have packaged an ApiRequest
class to manage network requests and error handling uniformly.
(I) Singleton Pattern
The ApiRequest
class uses the singleton pattern to ensure that there is only one global instance.
import { DataResult, ErrorCodes, ErrorData, LibToast, NetworkException, SuccessData } from "lib_base";
import { RcpNetworkService } from "lib_base/src/main/ets/utils/rcpnet/RcpService";
import { ApiResult } from "../data/models/ApiResult";
import { ApiException } from "./ApiException";
export interface IApiRequestHandleBusinessError{
handleBusinessError(apiException: ApiException): boolean
}
export class ApiRequest{
private static instance: ApiRequest
static getInstance (): ApiRequest {
if (!ApiRequest.instance) {
ApiRequest.instance = new ApiRequest()
}
return ApiRequest.instance
}
private _net?: RcpNetworkService | undefined;
private _i_api_equest_handle_business_error?: IApiRequestHandleBusinessError | undefined;
public set i_api_equest_handle_business_error(value: IApiRequestHandleBusinessError | undefined) {
this._i_api_equest_handle_business_error = value;
}
public set net(value: RcpNetworkService | undefined) {
this._net = value;
}
public getService() : RcpNetworkService{
return this._net!;
}
}
Core Points Analysis:
-
Singleton Pattern: The
getInstance
method ensures the global uniqueness of theApiRequest
instance. -
Dependency Injection: The
set
method is used to injectRcpNetworkService
andIApiRequestHandleBusinessError
, enhancing the flexibility of the class.
(II) Unified Request Method
The ApiRequest
class provides a unified request method remoteApi
to handle network requests and encapsulate the return results.
export interface IApiRequestHandleBusinessError {
handleBusinessError(apiException: ApiException): boolean;
}
export class ApiRequest {
public static async remoteApi<T>(api:()=>Promise<ApiResult<T>>): Promise<DataResult<ApiResult<T>|null>>{
try{
const data = await api()
if(data.success && data.success){
let bean = new SuccessData<ApiResult<T>>(data)
return bean;
} else {
let bean = ErrorData.fromError(new ApiException(data.code,data.msg) as Error,data.code?.toString(),data.msg)
return bean;
}
}catch (e) {
if(e instanceof NetworkException){
let bean = ErrorData.fromError(e)
// Request was canceled by the framework, client does not enter exception handling to avoid business pop-ups
if(e.code !== ErrorCodes.REQUEST_CANCEL){
LibToast.show(e.message)
}
return bean;
}
throw e as Error
}
}
}
Core Points Analysis:
-
Request Execution: The specific network request is executed through the
api
function passed in. -
Success Handling: If the request is successful, a
SuccessData
object is returned. -
Failure Handling: If the request fails, an
ErrorData
object is returned based on the error type. -
Network Exception Handling:
NetworkException
is caught, and a prompt message is displayed based on the error code.
(III) Business Logic Handling
The ApiRequest
class also provides a service
method to handle business logic and errors.
export class ApiRequest {
// ... Other code ...
public static async service<T>(source:()=>Promise<DataResult<ApiResult<T>|null>>,
request : (data:DataResult<T|null>)=>void,
apiError : (apiError:ErrorData)=>void,
netError? : (netError:ErrorData)=>void,
){
let data = await source();
if(data instanceof SuccessData){
request(data.data)
}else {
let error = data as ErrorData
if(error.error&&error.error instanceof ApiException){
// Business exception
if(ApiRequest.instance._i_api_equest_handle_business_error){
ApiRequest.instance._i_api_equest_handle_business_error.handleBusinessError(error.error)
}
apiError(error)
}else {
// Network exception
if(netError){
netError(error)
}
}
}
}
}
Core Points Analysis:
-
Request Execution: The network request is executed through the
source
function. -
Success Handling: If the request is successful, the
request
callback function is called to handle the data. -
Error Handling: The
apiError
ornetError
callback function is called based on the error type. -
Business Logic Separation: Business logic errors are handled through the
IApiRequestHandleBusinessError
interface.
III. Packaging Common Request Headers
In actual development, many requests need to carry common request headers, such as device information, user tokens, etc. You have packaged the common request headers through the CommonHeaderInterceptor
class.
export async function getCommonHeaders(): Promise<Record<string, string>> {
return {
"device": LibDevice.getDeviceInfo(),
"machineCode": await USystem.getUniqueKey(),
"terminalType": "1", // Example terminal type
"timestamp": new Date().toISOString(),
"versionNumber": LibDevice.getAppVersionCode().toString(),
"osId": Platform.appPlatform, // Example osId
"versionCode": LibDevice.getAppVersionName(),
"token": AccountManager.getToken()
};
}
export class CommonHeaderInterceptor implements rcp.Interceptor {
async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
const commonHeaders = await getCommonHeaders();
const keys = Object.keys(commonHeaders);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (!context.request.headers) {
context.request.headers = {};
}
context.request.headers[key] = commonHeaders[key];
}
return next.handle(context);
}
}
Core Points Analysis:
-
Common Header Information: Common header information is obtained through the
getCommonHeaders
function. -
Interceptor Implementation: In the
intercept
method, common header information is added to the request headers. - Dynamic Addition: Common header information is dynamically added through a loop to ensure that each request carries the necessary information.
IV. Packaging Response Converter
To better handle response data, a CommonTextResponseConverter
class is packaged to handle response content.
export class CommonTextResponseConverter extends TextResponseConverter {
convert(response: rcp.Response): string | object | null {
if (response.toJSON()) {
return response.toJSON();
} else {
return super.convert(response);
}
}
}
Core Points Analysis:
- JSON Conversion: Prioritize converting the response content to JSON format.
-
Fallback Handling: If it cannot be converted to JSON, call the
convert
method of the parent class to handle the response content.
V. Practical Application Case: Obtaining Sports Data
Assuming we need to obtain the user's sports data from the server, such as sports records and sports plans, we will implement this function through the packaged RCP network library.
(I) Packaging Request Method
export async function getAllLookSubjectList(params: Record<"parentId", string>, requestKeyFun?: (str: string) => void): Promise<ApiResult<Subject[]>> {
return ApiRequest.getInstance().getService().request<ApiResult<Subject[]>>>({
act: AllLOOK_SUBJECT_LIST,
method: RequestMethod.POST,
contentType: RcpContentType.JSON,
content: params
}, requestKeyFun);
}
Core Points Analysis:
-
Request Configuration: The basic information of the request, such as API path, request method, and content type, is configured through
RequestOptions
. -
Request Sending: The request is sent using the
ApiRequest.getInstance().getService().request
method. -
Callback Function: The request key value is provided through
requestKeyFun
for operations such as canceling the request.
(II) Calling Request Method
In actual pages or components, we can call the packaged request method to obtain sports data.
aboutToAppear(): void {
super.aboutToAppear();
this.showLoading();
ApiRequest.service<Subject[]>(() => {
return LookResponsitory.getInstance().getAllLookSubjectList("1", (requestKey) => {
if (requestKey) {
this.addRequestId(requestKey);
}
});
}, (data) => {
this.hideLoading();
if (data.data && data.data.length > 0) {
this.tabs = data.data;
} else {
this.setDefalutTab();
}
}, (apiError) => {
this.hideLoading();
this.setDefalutTab();
// Business exception
// LibToast.show(apiError.message ?? "Get exception");
}, () => {
this.hideLoading();
this.setDefalutTab();
// Network and other exceptions
// LibToast.show("Network exception");
});
}
Core Points Analysis:
-
Request Execution: The network request is executed through the
ApiRequest.service
method. - Success Handling: If the request is successful, handle the returned data.
- Error Handling: Call the corresponding callback function to handle the error based on the error type.
- Loading Status: Display the loading status at the start of the request and hide it at the end of the request.
VI. Summary
Through the practical case in this part, we have demonstrated how to use the packaged RCP network library to implement specific network request functions. By defining exception classes, packaging request methods, handling common request headers and response converters, and implementing specific request logic, we can efficiently complete network request tasks. The packaged network library not only provides basic request and response handling functions but also has advanced features such as error handling, log recording, session management, and network status detection, which can meet the needs of most network request scenarios.
Top comments (0)