Read the original article:Practical Guide: Mastering HarmonyOS Network Request Development
Contents
- Preface 
- Feature Overview 
- 
Implementation of the Request Utility Class - File Location
- Core Code
 
- Data Type Definition 
- 
Practical Application - Using Network Requests in Pages
- Implementing the Search Result Page
 
- 
Feature Demonstration - Home
- Search Result Page
 
- Summary 
Preface
Hello everyone, I am Ruocheng. This series aims to help developers quickly implement commonly used features in HarmonyOS apps, providing ready-to-use code examples. In this article, we will focus on encapsulating and applying network requests, enabling developers to easily make API calls. Basic concepts will not be elaborated in detail here. Please handle permission requests and related configurations as needed.
Feature Overview
This article provides a detailed explanation of the following:
- Encapsulation of basic HTTP request methods
- Practical design of an HTTP request utility class
- Type definitions and API specifications
- Actual use case examples
With these concepts, developers can quickly build their own network request layer and extend it to meet project requirements. Without further ado, let us get started.
Implementation of the Request Utility Class
File Location
Save the following code as Request.ets under the utils directory in your project:
Core Code
Below is the encapsulated Request.ets file — ready for direct use.
import { http } from '@kit.NetworkKit'
import { promptAction, router } from '@kit.ArkUI'
// Constant definitions
export const TOKEN_KEY: string = 'token'
export const BASE_URL: string = 'xxxxx' // Your API endpoint
/**
 * API response data structure
 */
export class ResponsesData<T> {
    code: number = 0
    msg: string = ""
    data: T | null = null
}
interface EmptyInterface {}
/**
 * Basic HTTP request method
 * @param url Request path
 * @param method Request method
 * @param data Request parameters
 * @returns Promise<T>
 */
async function requestHttp<T>(url: string = '', method: http.RequestMethod = http.RequestMethod.GET, data?: object): Promise<T> {
    // Create an HTTP request instance
    const httpRequest = http.createHttp()
    // Concatenate the complete URL
    let urlStr = BASE_URL + url
    // Process GET request parameters
    if (method === http.RequestMethod.GET) {
        if (data && Object.keys(data).length) {
            const queryParams = Object.keys(data)
                .filter(key => data[key] !== undefined && data[key] !== null)
                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
                .join('&')
            if (queryParams) {
                urlStr += "?" + queryParams
            }
        }
    }
    // Request configuration
    const config: http.HttpRequestOptions = {
        method,
        readTimeout: 10000,
        // No extraData required for GET requests
        extraData: method === http.RequestMethod.GET ? '' : data || {} as EmptyInterface,
        header: {
            'Content-Type': 'application/json',
            "Authorization": AppStorage.get(TOKEN_KEY) as string || ''
        }
    }
    try {
        // Send the request
        const res = await httpRequest.request(urlStr, config)
        console.info(`[HTTP ${method}] ${urlStr}`)
        // Process HTTP status codes
        switch (res.responseCode) {
            case 401:
                // Processing authentication failure
                AppStorage.set<string>(TOKEN_KEY, '')
                promptAction.showToast({ message: 'Token expired.' })
                router.replaceUrl({ url: 'pages/Login/LoginPage' })
                return Promise.reject(new Error(Token expired.'))
            case 404:
                promptAction.showToast({ message: 'Invalid request URL.' })
                return Promise.reject(new Error('Invalid request URL.'))
            default:
                // Parse the response data
                const result = JSON.parse(res.result as string) as ResponsesData<T>
                if (result.code === 200) {
                    return result.data as T
                } else {
                    promptAction.showToast({ message: result.msg || 'Server error.' })
                    return Promise.reject(new Error(result.msg))
                }
        }
    } catch (error) {
        promptAction.showToast({ message: `Request failed: ${error}` })
        return Promise.reject(error)
    } finally {
        // Release resources
        httpRequest.destroy()
    }
}
/**
 * HTTP request utility class
 */
export class Request {
    /**
     * GET request
 * @param url Request path
 * @param data Request parameters
     */
    static get<T>(url: string, data?: object): Promise<T> {
        return requestHttp<T>(url, http.RequestMethod.GET, data)
    }
    /**
     * POST request
 * @param url Request path
     * @param data Request body
     */
    static post<T>(url: string, data?: object): Promise<T> {
        return requestHttp<T>(url, http.RequestMethod.POST, data)
    }
    /**
     * PUT request
 * @param url Request path
     * @param data Request body
     */
    static put<T>(url: string, data?: object): Promise<T> {
        return requestHttp<T>(url, http.RequestMethod.PUT, data)
    }
    /**
     * DELETE request
 * @param url Request path
 * @param data Request parameters
     */
    static delete<T>(url: string, data?: object): Promise<T> {
        return requestHttp<T>(url, http.RequestMethod.DELETE, data)
    }
}
Data Type Definition
To better manage data structures, create a file named types.ets to define API types:
// Food category API
export interface Category {
  name: string;
  icon: Resource;
}
// Food data API
export interface FoodItem {
  name: string;
  img: string;
  calory: string;
}
// Common food data API
export interface CommonFood {
  category: string;
  name: string;
  img: string;
  calory: string;
}
// API response data
export interface ResponseData {
    keyword: string;
    Lists: FoodItem[]
}
Practical Application
Using Network Requests in Pages
First, import the necessary modules:
import { FoodItem, ResponseData } from '../utils/types';
import { Request } from "../utils/request"
Then, implement the search feature:
// Search feature
searchFood(keyword: string): void {
    Request.get<ResponseData>(`?key=xxxxxxx&food=${keyword}`).then(res => {
        console.log('Search result', JSON.stringify(res))
        this.searchResults = res.Lists
        router.pushUrl({
            url: "pages/SearchResult",
            params: res.Lists
        })
    })
}
Note: For the home page implementation and related content, please refer to the previous article.
Implementing the Search Result Page
import { FoodItem, ResponseData } from '../utils/types';
import { router, Router } from '@kit.ArkUI';
@Entry
@Component
struct SearchResult {
    @State message: string = 'Hello World';
    @State searchResults: FoodItem[] = []
    aboutToAppear(): void {
        const params = router.getParams() as FoodItem[]
        console.log("Result page", JSON.stringify(params))
        this.searchResults = params
    }
    build() {
        // Display search results
        List() {
            ForEach(this.searchResults, (item: FoodItem) => {
                ListItem() {
                    this.FoodItem(item)
                }
            })
        }
        .width('100%')
        .layoutWeight(1)
        .listDirection(Axis.Vertical)
        .edgeEffect(EdgeEffect.Spring)
        .padding({ top: 8, bottom: 16 })
        .backgroundColor('#F8F8F8')
    }
    @Builder
    FoodItem(item: FoodItem) {
        Column() {
            Row() {
                Image(item.img)
                    .width(80)
                    .height(80)
                    .borderRadius(12)
                    .backgroundColor('#F0F0F0')
                    .margin({ right: 16 })
                    .objectFit(ImageFit.Cover)
                    .alt($r('app.media.food'))
                Column() {
                    Text(item.name)
                        .fontSize(18)
                        .fontWeight(FontWeight.Medium)
                        .margin({ bottom: 8 })
                        .maxLines(1)
                        .textOverflow({ overflow: TextOverflow.Ellipsis })
                }
                .alignItems(HorizontalAlign.Start)
                .layoutWeight(1)
                .justifyContent(FlexAlign.Center)
            }
            .width('100%')
            .padding(16)
        }
        .backgroundColor(Color.White)
        .borderRadius(16)
        .shadow({ radius: 8, color: 'rgba(0, 0, 0, 0.08)', offsetY: 2 })
        .margin({ bottom: 12, left: 16, right: 16 })
    }
}
Feature Demonstration
Home
Search Result Page
Summary
This article explained how to encapsulate an HTTP request utility class in a HarmonyOS app and demonstrated its use through a practical example. With this encapsulation approach, we can greatly simplify the implementation of network requests, improving code maintainability and scalability. Hope this article helps you in your HarmonyOS app development journey. Class dismissed.
 




 
    
Top comments (0)