2  第1章 ArkTS高级语法与编程范式

HarmonyOS应用开发者高级认证教程

Author

HarmonyOS技术专家

3 第1章 ArkTS高级语法与编程范式

3.1 学习目标

完成本章学习后,你将能够:

  • 深入理解ArkTS与TypeScript的关系、设计理念及约束差异
  • 掌握ArkTS高级类型系统,包括泛型约束、条件类型、装饰器等
  • 熟练运用异步编程模式,包括Promise高级用法、TaskPool和Worker线程
  • 理解并应用函数式编程范式,包括高阶函数、闭包、柯里化等
  • 掌握模块系统与工程化最佳实践
  • 具备高级错误处理与调试能力

3.2 1.1 ArkTS与TypeScript的关系和区别

3.2.1 1.1.1 ArkTS的设计理念

ArkTS是华为基于TypeScript扩展开发的声明式UI编程语言,是HarmonyOS应用开发的主力语言。它在继承TypeScript强大类型系统的基础上,针对HarmonyOS平台做了以下关键设计:

设计目标:

  1. 简洁性:减少代码量,提高开发效率
  2. 高性能:通过编译时优化和静态类型约束,实现更好的运行时性能
  3. 声明式UI:提供原生的声明式UI构建能力
  4. 安全可控:通过更严格的类型检查减少运行时错误

ArkTS的核心约束:

// ArkTS不允许使用any类型(TypeScript中的"逃逸舱口"被禁用)
// 以下代码在ArkTS中会报错:
// let value: any = "hello"  // 编译错误!

// 必须使用明确的类型声明
let value: string = "hello"
let count: number = 42
let isValid: boolean = true

// 不允许使用联合类型中包含any的情况
// let mixed: string | any  // 编译错误!

// 必须使用unknown替代需要动态类型的场景
let dynamic: unknown = "hello"
if (typeof dynamic === 'string') {
    // 类型收窄后可以安全使用
    let str: string = dynamic
}

ArkTS对TypeScript的限制:

// 1. 禁止动态属性访问
interface User {
    name: string
    age: number
}

let user: User = { name: "张三", age: 25 }
// user["name"]  // 在ArkTS中不推荐使用,应使用点号访问
let userName: string = user.name  // 推荐方式

// 2. 禁止在运行时改变对象结构
// 不能动态添加属性
// user.phone = "123456"  // 编译错误

// 3. 函数参数必须声明类型
function greet(name: string, age: number): string {
    return `你好,${name},你今年${age}岁`
}

// 4. 不允许使用eval()
// eval("console.log('hello')")  // 编译错误!

// 5. 不允许使用with语句
// with (obj) { ... }  // 编译错误!

3.2.2 1.1.2 静态类型检查的增强

ArkTS在编译阶段执行更严格的类型检查,以确保应用的质量和性能:

// 1. 严格的函数返回类型推断
function calculateTotal(price: number, quantity: number): number {
    return price * quantity
}

// 2. 枚举类型的严格使用
enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT"
}

function move(dir: Direction): void {
    switch (dir) {
        case Direction.Up:
            console.log("向上移动")
            break
        case Direction.Down:
            console.log("向下移动")
            break
        case Direction.Left:
            console.log("向左移动")
            break
        case Direction.Right:
            console.log("向右移动")
            break
        // ArkTS要求switch语句必须穷举所有枚举值
        // 或者提供default分支
    }
}

// 3. 严格的null检查
// ArkTS默认启用严格空检查
let name: string | null = null
// let len: number = name.length  // 编译错误!name可能为null

// 必须使用可选链或空值合并运算符
let len: number = name?.length ?? 0
console.log(`名字长度: ${len}`)

// 4. 类型断言的限制
let unknownValue: unknown = "hello"
// let str: string = unknownValue as string  // ArkTS限制使用as断言
// 推荐使用类型守卫
if (typeof unknownValue === 'string') {
    let str: string = unknownValue  // 安全的类型收窄
    console.log(str.toUpperCase())
}

3.2.3 1.1.3 ArkTS对TypeScript的扩展

ArkTS在TypeScript基础上增加了以下扩展能力:

// 1. 声明式UI扩展 - 装饰器语法
@Component
struct MyComponent {
    @State message: string = "Hello HarmonyOS"

    build() {
        Column() {
            Text(this.message)
                .fontSize(24)
                .fontWeight(FontWeight.Bold)
            Button("点击更新")
                .onClick(() => {
                    this.message = "Hello World"
                })
        }
    }
}

// 2. 自定义组件装饰器
@Observed
class UserModel {
    name: string = ""
    age: number = 0

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

// 3. 入口组件装饰器
@Entry
@Component
struct Index {
    @State counter: number = 0

    build() {
        Column() {
            Text(`计数器: ${this.counter}`)
                .fontSize(30)
            Row() {
                Button("+1")
                    .onClick(() => { this.counter++ })
                Button("-1")
                    .onClick(() => { this.counter-- })
            }
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
    }
}

// 4. Builder装饰器 - 可复用的UI构建函数
@Component
struct ListComponent {
    @Builder itemBuilder(title: string, subtitle: string) {
        Row() {
            Column() {
                Text(title).fontSize(18).fontWeight(FontWeight.Medium)
                Text(subtitle).fontSize(14).fontColor('#666666')
            }
            .alignItems(HorizontalAlign.Start)
            .layoutWeight(1)
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#FFFFFF')
    }

    build() {
        List() {
            ListItem() { this.itemBuilder("项目一", "这是描述信息") }
            ListItem() { this.itemBuilder("项目二", "这是另一条描述") }
            ListItem() { this.itemBuilder("项目三", "更多信息") }
        }
        .width('100%')
        .height('100%')
    }
}

3.3 1.2 高级类型系统

3.3.1 1.2.1 联合类型与交叉类型

联合类型(Union Types)和交叉类型(Intersection Types)是ArkTS类型系统中的高级特性:

// 联合类型 - 表示值可以是多种类型之一
type StringOrNumber = string | number

function formatValue(value: StringOrNumber): string {
    if (typeof value === 'string') {
        return value.toUpperCase()
    } else {
        return value.toFixed(2)
    }
}

// 交叉类型 - 合并多个类型
interface HasName {
    name: string
}

interface HasAge {
    age: number
}

interface HasEmail {
    email: string
}

// 交叉类型组合多个接口
type Person = HasName & HasAge & HasEmail

let person: Person = {
    name: "李四",
    age: 30,
    email: "lisi@example.com"
}

// 实际应用场景:组件属性合并
interface BaseProps {
    id: string
    className?: string
}

interface ClickableProps {
    onClick: () => void
}

interface StyleProps {
    color: string
    fontSize: number
}

// 按钮组件需要同时具备基础属性、可点击属性和样式属性
type ButtonProps = BaseProps & ClickableProps & StyleProps

let buttonConfig: ButtonProps = {
    id: "btn-submit",
    className: "primary",
    onClick: () => { console.log("按钮被点击") },
    color: "#FF0000",
    fontSize: 16
}

3.3.2 1.2.2 类型守卫与类型收窄

类型守卫是安全处理联合类型的关键机制:

// 1. typeof类型守卫
function processInput(input: string | number | boolean): string {
    if (typeof input === 'string') {
        // 此处input被收窄为string类型
        return input.toUpperCase()
    } else if (typeof input === 'number') {
        // 此处input被收窄为number类型
        return input.toFixed(2)
    } else {
        // 此处input被收窄为boolean类型
        return input ? "是" : "否"
    }
}

// 2. in操作符类型守卫
interface Fish {
    swim: () => void
    name: string
}

interface Bird {
    fly: () => void
    name: string
}

function move(animal: Fish | Bird): void {
    if ('swim' in animal) {
        // animal被收窄为Fish类型
        animal.swim()
    } else {
        // animal被收窄为Bird类型
        animal.fly()
    }
}

// 3. 自定义类型守卫(类型谓词)
interface SuccessResult {
    code: 200
    data: string
}

interface ErrorResult {
    code: 400 | 500
    message: string
}

type ApiResult = SuccessResult | ErrorResult

// 自定义类型守卫函数
function isSuccess(result: ApiResult): result is SuccessResult {
    return result.code === 200
}

function handleResult(result: ApiResult): void {
    if (isSuccess(result)) {
        // result被收窄为SuccessResult
        console.log(`数据: ${result.data}`)
    } else {
        // result被收窄为ErrorResult
        console.log(`错误: ${result.message}`)
    }
}

// 4. instanceof类型守卫
class NetworkError extends Error {
    statusCode: number

    constructor(message: string, statusCode: number) {
        super(message)
        this.statusCode = statusCode
    }
}

class TimeoutError extends Error {
    timeout: number

    constructor(message: string, timeout: number) {
        super(message)
        this.timeout = timeout
    }
}

function handleError(error: NetworkError | TimeoutError): string {
    if (error instanceof NetworkError) {
        return `网络错误,状态码: ${error.statusCode}`
    } else {
        return `请求超时,超时时间: ${error.timeout}ms`
    }
}

3.3.3 1.2.3 泛型的高级用法

泛型是实现代码复用和类型安全的核心工具:

// 1. 泛型约束
interface HasLength {
    length: number
}

// 泛型约束:T必须有length属性
function logLength<T extends HasLength>(value: T): void {
    console.log(`长度: ${value.length}`)
}

logLength("hello")       // string有length属性
logLength([1, 2, 3])     // Array有length属性
// logLength(123)         // 编译错误!number没有length属性

// 2. 泛型约束 - 键约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key]
}

interface Product {
    id: number
    name: string
    price: number
}

let product: Product = { id: 1, name: "手机", price: 2999 }
let productName: string = getProperty(product, "name")    // 类型安全
let productPrice: number = getProperty(product, "price")  // 类型安全
// getProperty(product, "invalid")  // 编译错误!"invalid"不是Product的键

// 3. 条件类型
type IsString<T> = T extends string ? true : false
type Result1 = IsString<string>   // true
type Result2 = IsString<number>   // false

// 条件类型实际应用:API响应处理
type ApiResponse<T> = T extends string
    ? { text: T }
    : T extends number
    ? { value: T }
    : { data: T }

type StringResponse = ApiResponse<string>  // { text: string }
type NumberResponse = ApiResponse<number>  // { value: number }
type ObjectResponse = ApiResponse<Product> // { data: Product }

// 4. 泛型工具类型
// 实现Partial - 将所有属性变为可选
type MyPartial<T> = {
    [K in keyof T]?: T[K]
}

// 实现Required - 将所有属性变为必需
type MyRequired<T> = {
    [K in keyof T]-?: T[K]
}

// 实现Pick - 从类型中选取部分属性
type MyPick<T, K extends keyof T> = {
    [P in K]: T[P]
}

// 实现Omit - 从类型中排除部分属性
type MyOmit<T, K extends keyof T> = {
    [P in Exclude<K, keyof T> | Exclude<keyof T, K>]: T[P]
}

// 实际应用
type ProductSummary = MyPick<Product, "id" | "name">
// 等价于 { id: number; name: string }

type ProductUpdate = MyPartial<MyOmit<Product, "id">>
// 等价于 { name?: string; price?: number }

// 5. 泛型类
class Stack<T> {
    private items: T[] = []

    push(item: T): void {
        this.items.push(item)
    }

    pop(): T | undefined {
        return this.items.pop()
    }

    peek(): T | undefined {
        return this.items[this.items.length - 1]
    }

    isEmpty(): boolean {
        return this.items.length === 0
    }

    size(): number {
        return this.items.length
    }
}

// 使用泛型类
let numberStack = new Stack<number>()
numberStack.push(1)
numberStack.push(2)
numberStack.push(3)
let top: number | undefined = numberStack.pop()  // 3

let stringStack = new Stack<string>()
stringStack.push("Hello")
stringStack.push("World")

3.3.4 1.2.4 装饰器与元编程

装饰器是ArkTS中实现元编程的重要手段,尤其在UI框架中广泛应用:

// 1. 类装饰器 - 用于类的声明
function logClass(target: Function): void {
    console.log(`类被创建: ${target.name}`)
}

// 2. 属性装饰器
function logProperty(target: Object, propertyKey: string): void {
    console.log(`属性: ${propertyKey}`)
}

// 3. 方法装饰器
function logMethod(
    target: Object,
    propertyKey: string,
    descriptor: PropertyDescriptor
): PropertyDescriptor {
    const originalMethod = descriptor.value
    descriptor.value = function (...args: Object[]): Object {
        console.log(`调用方法 ${propertyKey},参数: ${JSON.stringify(args)}`)
        const result = originalMethod.apply(this, args)
        console.log(`方法 ${propertyKey} 返回: ${JSON.stringify(result)}`)
        return result
    }
    return descriptor
}

// 4. 实际应用场景:HarmonyOS中的状态管理装饰器
// @Observed 装饰器使类具备观察能力
@Observed
class TaskItem {
    title: string
    completed: boolean
    priority: number

    constructor(title: string, priority: number = 0) {
        this.title = title
        this.completed = false
        this.priority = priority
    }

    toggle(): void {
        this.completed = !this.completed
    }
}

// @ObservedV2 是V2版本的状态管理装饰器
@ObservedV2
class ShoppingCart {
    @Trace items: string[] = []
    @Trace totalPrice: number = 0

    addItem(item: string, price: number): void {
        this.items.push(item)
        this.totalPrice += price
    }

    removeItem(index: number): void {
        this.items.splice(index, 1)
    }
}

// 5. 自定义装饰器实现缓存功能
function memoize(
    target: Object,
    propertyKey: string,
    descriptor: PropertyDescriptor
): PropertyDescriptor {
    const originalMethod = descriptor.value
    const cache = new Map<string, Object>()

    descriptor.value = function (...args: Object[]): Object {
        const key = JSON.stringify(args)
        if (cache.has(key)) {
            return cache.get(key)
        }
        const result = originalMethod.apply(this, args)
        cache.set(key, result)
        return result
    }
    return descriptor
}

3.4 1.3 异步编程深入

3.4.1 1.3.1 Promise链式调用与错误处理

Promise是异步编程的基础,掌握其高级用法对于构建复杂应用至关重要:

// 1. Promise链式调用的最佳实践
interface UserInfo {
    id: number
    name: string
    email: string
}

interface UserOrders {
    userId: number
    orders: string[]
}

interface OrderDetail {
    orderId: string
    amount: number
    status: string
}

// 模拟API调用
function fetchUserInfo(userId: number): Promise<UserInfo> {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ id: userId, name: "张三", email: "zhangsan@example.com" })
        }, 1000)
    })
}

function fetchUserOrders(userId: number): Promise<UserOrders> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({ userId: userId, orders: ["ORD001", "ORD002", "ORD003"] })
        }, 800)
    })
}

function fetchOrderDetail(orderId: string): Promise<OrderDetail> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({ orderId: orderId, amount: 99.9, status: "已完成" })
        }, 500)
    })
}

// 链式调用 - 获取用户信息 -> 获取订单列表 -> 获取第一个订单详情
function getUserFirstOrder(userId: number): Promise<OrderDetail> {
    return fetchUserInfo(userId)
        .then((userInfo: UserInfo): Promise<UserOrders> => {
            console.log(`获取到用户信息: ${userInfo.name}`)
            return fetchUserOrders(userInfo.id)
        })
        .then((userOrders: UserOrders): Promise<OrderDetail> => {
            if (userOrders.orders.length === 0) {
                throw new Error("用户没有订单")
            }
            return fetchOrderDetail(userOrders.orders[0])
        })
        .catch((error: Error): Promise<OrderDetail> => {
            console.error(`获取订单详情失败: ${error.message}`)
            // 返回默认值或重新抛出错误
            return Promise.reject(error)
        })
}

// 2. 错误处理策略
// 策略一:在链的末尾统一处理
fetchUserInfo(1)
    .then((info: UserInfo) => fetchUserOrders(info.id))
    .then((orders: UserOrders) => {
        console.log(`订单数量: ${orders.orders.length}`)
    })
    .catch((error: Error) => {
        console.error(`统一错误处理: ${error.message}`)
    })
    .finally(() => {
        console.log("请求完成,无论成功失败都会执行")
    })

// 策略二:分层错误处理
async function loadDataWithRetry(
    userId: number,
    maxRetries: number = 3
): Promise<UserInfo> {
    let lastError: Error = new Error("未知错误")

    for (let attempt: number = 1; attempt <= maxRetries; attempt++) {
        try {
            let userInfo: UserInfo = await fetchUserInfo(userId)
            console.log(`第${attempt}次尝试成功`)
            return userInfo
        } catch (error) {
            lastError = error as Error
            console.warn(`第${attempt}次尝试失败: ${lastError.message}`)
            if (attempt < maxRetries) {
                // 指数退避
                await new Promise<void>((resolve) =>
                    setTimeout(resolve, Math.pow(2, attempt) * 1000)
                )
            }
        }
    }
    throw lastError
}

3.4.2 1.3.2 async/await高级模式

// 1. 并行执行多个异步操作
async function loadDashboardData(userId: number): Promise<void> {
    // 并行请求 - 所有请求同时发出
    let userInfoPromise: Promise<UserInfo> = fetchUserInfo(userId)
    let ordersPromise: Promise<UserOrders> = fetchUserOrders(userId)

    try {
        // 等待所有并行请求完成
        let [userInfo, orders]: [UserInfo, UserOrders] =
            await Promise.all([userInfoPromise, ordersPromise])

        console.log(`用户: ${userInfo.name}, 订单数: ${orders.orders.length}`)
    } catch (error) {
        console.error(`加载仪表板数据失败: ${(error as Error).message}`)
    }
}

// 2. 串行与并行混合
async function processBatchData(userIds: number[]): Promise<OrderDetail[]> {
    let allDetails: OrderDetail[] = []

    for (let userId of userIds) {
        // 每个用户的订单并行获取
        let orders: UserOrders = await fetchUserOrders(userId)
        let detailPromises: Promise<OrderDetail>[] =
            orders.orders.map((id: string) => fetchOrderDetail(id))
        let details: OrderDetail[] = await Promise.all(detailPromises)
        allDetails = allDetails.concat(details)
    }

    return allDetails
}

// 3. 异步迭代器模式
async function* asyncDataGenerator(count: number): AsyncGenerator<number> {
    for (let i: number = 0; i < count; i++) {
        // 模拟异步数据获取
        await new Promise<void>((resolve) => setTimeout(resolve, 100))
        yield i
    }
}

// 使用异步迭代器
async function processData(): Promise<void> {
    for await (let value of asyncDataGenerator(5)) {
        console.log(`处理数据: ${value}`)
    }
}

// 4. 超时控制
async function fetchWithTimeout<T>(
    promise: Promise<T>,
    timeoutMs: number
): Promise<T> {
    let timeoutPromise: Promise<T> = new Promise<T>((_, reject) => {
        setTimeout(() => {
            reject(new Error(`请求超时 (${timeoutMs}ms)`))
        }, timeoutMs)
    })

    return Promise.race([promise, timeoutPromise])
}

// 使用超时控制
async function loadWithTimeout(): Promise<void> {
    try {
        let userInfo: UserInfo = await fetchWithTimeout(
            fetchUserInfo(1),
            3000  // 3秒超时
        )
        console.log(`加载成功: ${userInfo.name}`)
    } catch (error) {
        console.error(`加载失败: ${(error as Error).message}`)
    }
}

3.4.3 1.3.3 并发控制

// 1. Promise.all - 所有成功才成功
async function fetchAllUserData(userId: number): Promise<void> {
    try {
        let results: [UserInfo, UserOrders] = await Promise.all([
            fetchUserInfo(userId),
            fetchUserOrders(userId)
        ])
        console.log(`用户信息: ${results[0].name}`)
        console.log(`订单数量: ${results[1].orders.length}`)
    } catch (error) {
        // 任何一个Promise失败,整体失败
        console.error(`获取数据失败: ${(error as Error).message}`)
    }
}

// 2. Promise.allSettled - 等待所有完成,不论成功失败
async function fetchAllSettled(): Promise<void> {
    let promises: Promise<UserInfo>[] = [
        fetchUserInfo(1),
        fetchUserInfo(2),
        fetchUserInfo(3)
    ]

    let results: PromiseSettledResult<UserInfo>[] =
        await Promise.allSettled(promises)

    for (let result of results) {
        if (result.status === 'fulfilled') {
            console.log(`成功: ${result.value.name}`)
        } else {
            console.log(`失败: ${result.reason}`)
        }
    }
}

// 3. Promise.race - 取最先完成的
async function fetchFastest(): Promise<UserInfo> {
    // 从多个数据源获取,使用最快的
    return Promise.race([
        fetchUserInfo(1),
        new Promise<UserInfo>((_, reject) =>
            setTimeout(() => reject(new Error("超时")), 5000)
        )
    ])
}

// 4. 并发限制器 - 控制同时执行的任务数量
class ConcurrencyLimiter {
    private concurrency: number
    private running: number = 0
    private queue: Array<() => void> = []

    constructor(concurrency: number) {
        this.concurrency = concurrency
    }

    async execute<T>(task: () => Promise<T>): Promise<T> {
        while (this.running >= this.concurrency) {
            await new Promise<void>((resolve) => this.queue.push(resolve))
        }

        this.running++
        try {
            return await task()
        } finally {
            this.running--
            if (this.queue.length > 0) {
                let next = this.queue.shift()
                if (next) next()
            }
        }
    }
}

// 使用并发限制器
async function batchProcess(): Promise<void> {
    let limiter = new ConcurrencyLimiter(3)  // 最多3个并发
    let tasks: Promise<void>[] = []

    for (let i: number = 0; i < 10; i++) {
        let userId = i
        tasks.push(
            limiter.execute(async () => {
                let info: UserInfo = await fetchUserInfo(userId)
                console.log(`处理完成: ${info.name}`)
            })
        )
    }

    await Promise.all(tasks)
    console.log("所有任务处理完成")
}

3.4.4 1.3.4 TaskPool和Worker线程

HarmonyOS提供了TaskPool和Worker两种多线程方案:

// 1. TaskPool - 推荐的高性能并发方案
import taskpool from '@ohos.taskpool'

// 定义可以在TaskPool中执行的任务
@Concurrent
function computeHeavyTask(data: number[]): number {
    let sum: number = 0
    for (let i: number = 0; i < data.length; i++) {
        sum += data[i] * data[i]
    }
    return sum
}

// 在组件中使用TaskPool
@Component
struct TaskPoolExample {
    @State result: string = "等待计算..."
    @State isLoading: boolean = false

    async startComputation(): Promise<void> {
        this.isLoading = true
        let data: number[] = []
        for (let i: number = 0; i < 10000; i++) {
            data.push(i)
        }

        try {
            // 创建TaskPool任务
            let task = new taskpool.Task(computeHeavyTask, data)
            // 执行任务
            let result: number = await taskpool.execute(task) as number
            this.result = `计算结果: ${result}`
        } catch (error) {
            this.result = `计算失败: ${(error as Error).message}`
        } finally {
            this.isLoading = false
        }
    }

    build() {
        Column() {
            Text(this.result).fontSize(18)
            Button("开始计算")
                .enabled(!this.isLoading)
                .onClick(() => { this.startComputation() })
        }
    }
}

// 2. TaskPool分组执行
@Concurrent
function processChunk(chunk: number[], offset: number): number {
    let sum: number = 0
    for (let i: number = 0; i < chunk.length; i++) {
        sum += chunk[i]
    }
    return sum
}

async function parallelProcess(data: number[], chunkSize: number): Promise<number> {
    let group = new taskpool.TaskGroup()

    for (let i: number = 0; i < data.length; i += chunkSize) {
        let chunk: number[] = data.slice(i, Math.min(i + chunkSize, data.length))
        group.addTask(new taskpool.Task(processChunk, chunk, i))
    }

    // 并行执行所有分块任务
    let results: number[] = await taskpool.execute(group) as number[]
    let total: number = 0
    for (let r of results) {
        total += r
    }
    return total
}

// 3. Worker线程 - 适合长期运行的后台任务
import worker from '@ohos.worker'

// worker线程文件 (worker/MyWorker.ts)
// import worker from '@ohos.worker'
//
// const workerPort = worker.workerPort
//
// workerPort.onmessage = (event: MessageEvents) => {
//     const data = event.data
//     // 执行耗时操作
//     const result = heavyComputation(data)
//     workerPort.postMessage(result)
// }
//
// function heavyComputation(data: number[]): number {
//     return data.reduce((sum: number, val: number) => sum + val, 0)
// }

// 在主线程中使用Worker
@Component
struct WorkerExample {
    @State workerResult: string = "等待Worker结果..."
    private myWorker: worker.ThreadWorker | null = null

    aboutToAppear(): void {
        // 创建Worker线程
        this.myWorker = new worker.ThreadWorker(
            'entry/ets/workers/MyWorker.ets'
        )

        // 接收Worker消息
        this.myWorker.onmessage = (e: MessageEvents) => {
            this.workerResult = `Worker计算结果: ${e.data}`
        }
    }

    aboutToDisappear(): void {
        // 销毁Worker线程
        if (this.myWorker) {
            this.myWorker.terminate()
            this.myWorker = null
        }
    }

    build() {
        Column() {
            Text(this.workerResult).fontSize(18)
            Button("发送数据到Worker")
                .onClick(() => {
                    if (this.myWorker) {
                        this.myWorker.postMessage([1, 2, 3, 4, 5])
                    }
                })
        }
    }
}

// 4. TaskPool vs Worker 选择指南
// TaskPool适用场景:
// - 计算密集型任务
// - 不需要与主线程频繁通信
// - 任务可以并行化
// - 短期运行的任务

// Worker适用场景:
// - 需要长期运行的后台任务
// - 需要与主线程频繁通信
// - 需要维护后台状态
// - 需要独立的执行环境

3.5 1.4 函数式编程范式

3.5.1 1.4.1 高阶函数

高阶函数是指接受函数作为参数或返回函数作为结果的函数:

// 1. 函数作为参数
function applyOperation(
    values: number[],
    operation: (x: number) => number
): number[] {
    return values.map(operation)
}

let numbers: number[] = [1, 2, 3, 4, 5]
let doubled: number[] = applyOperation(numbers, (x: number) => x * 2)
// [2, 4, 6, 8, 10]

let squared: number[] = applyOperation(numbers, (x: number) => x * x)
// [1, 4, 9, 16, 25]

// 2. 函数作为返回值
function createMultiplier(factor: number): (x: number) => number {
    return (x: number): number => x * factor
}

let double = createMultiplier(2)
let triple = createMultiplier(3)

console.log(double(5))   // 10
console.log(triple(5))   // 15

// 3. 函数组合
function compose<A, B, C>(
    f: (x: B) => C,
    g: (x: A) => B
): (x: A) => C {
    return (x: A): C => f(g(x))
}

// 使用示例
let addOne = (x: number): number => x + 1
let multiplyByTwo = (x: number): number => x * 2
let square = (x: number): number => x * x

// 组合函数:先加1,再乘2,再平方
let transform = compose(square, compose(multiplyByTwo, addOne))
console.log(transform(3))  // ((3+1)*2)^2 = 64

// 4. 管道操作
function pipe<A, B, C>(
    f: (x: A) => B,
    g: (x: B) => C
): (x: A) => C {
    return (x: A): C => g(f(x))
}

// 数据处理管道
type Product = { name: string; price: number; category: string }

let products: Product[] = [
    { name: "手机", price: 2999, category: "电子" },
    { name: "电脑", price: 5999, category: "电子" },
    { name: "T恤", price: 99, category: "服装" },
    { name: "裤子", price: 199, category: "服装" },
    { name: "耳机", price: 599, category: "电子" },
]

// 使用函数式管道处理数据
let electronicsOver500: Product[] = products
    .filter((p: Product): boolean => p.category === "电子")
    .filter((p: Product): boolean => p.price > 500)
    .sort((a: Product, b: Product): number => b.price - a.price)

console.log(electronicsOver500)
// [{ name: "电脑", price: 5999 }, { name: "手机", price: 2999 }]

// 5. 实际应用:事件处理函数工厂
function createDebouncedHandler(
    handler: (value: string) => void,
    delayMs: number
): (value: string) => void {
    let timerId: number = -1

    return (value: string): void => {
        if (timerId !== -1) {
            clearTimeout(timerId)
        }
        timerId = setTimeout(() => {
            handler(value)
            timerId = -1
        }, delayMs)
    }
}

// 在组件中使用防抖搜索
@Component
struct SearchComponent {
    @State searchText: string = ""
    private debouncedSearch: (value: string) => void =
        createDebouncedHandler((query: string) => {
            console.log(`搜索: ${query}`)
            // 执行搜索逻辑
        }, 300)

    build() {
        Column() {
            TextInput({ placeholder: "搜索..." })
                .onChange((value: string) => {
                    this.searchText = value
                    this.debouncedSearch(value)
                })
        }
    }
}

3.5.2 1.4.2 闭包与词法作用域

// 1. 闭包的基本概念
function createCounter(): () => number {
    let count: number = 0  // 被闭包捕获的变量

    return (): number => {
        count++
        return count
    }
}

let counter1 = createCounter()
console.log(counter1())  // 1
console.log(counter1())  // 2
console.log(counter1())  // 3

let counter2 = createCounter()  // 独立的闭包实例
console.log(counter2())  // 1

// 2. 闭包实现数据私有化
function createBankAccount(initialBalance: number) {
    let balance: number = initialBalance
    let transactions: string[] = []

    return {
        deposit: (amount: number): void => {
            if (amount <= 0) {
                throw new Error("存款金额必须大于0")
            }
            balance += amount
            transactions.push(`存入: ${amount}, 余额: ${balance}`)
        },
        withdraw: (amount: number): void => {
            if (amount <= 0 || amount > balance) {
                throw new Error("无效的取款金额")
            }
            balance -= amount
            transactions.push(`取出: ${amount}, 余额: ${balance}`)
        },
        getBalance: (): number => balance,
        getHistory: (): string[] => [...transactions]
    }
}

let account = createBankAccount(1000)
account.deposit(500)
account.withdraw(200)
console.log(account.getBalance())  // 1300
console.log(account.getHistory())
// ["存入: 500, 余额: 1500", "取出: 200, 余额: 1300"]

// 3. 闭包在HarmonyOS中的应用
@Component
struct TimerComponent {
    @State elapsedTime: number = 0
    @State isRunning: boolean = false
    private timerId: number = -1
    private startTime: number = 0

    private startTimer(): void {
        this.isRunning = true
        this.startTime = Date.now() - this.elapsedTime

        // 使用闭包捕获this引用
        this.timerId = setInterval(() => {
            this.elapsedTime = Date.now() - this.startTime
        }, 100)
    }

    private stopTimer(): void {
        this.isRunning = false
        if (this.timerId !== -1) {
            clearInterval(this.timerId)
            this.timerId = -1
        }
    }

    private formatTime(ms: number): string {
        let seconds: number = Math.floor(ms / 1000)
        let minutes: number = Math.floor(seconds / 60)
        let hours: number = Math.floor(minutes / 60)
        seconds = seconds % 60
        minutes = minutes % 60
        return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
    }

    aboutToDisappear(): void {
        this.stopTimer()
    }

    build() {
        Column({ space: 20 }) {
            Text(this.formatTime(this.elapsedTime))
                .fontSize(48)
                .fontWeight(FontWeight.Bold)

            Row({ space: 20 }) {
                Button(this.isRunning ? "暂停" : "开始")
                    .onClick(() => {
                        if (this.isRunning) {
                            this.stopTimer()
                        } else {
                            this.startTimer()
                        }
                    })
                Button("重置")
                    .onClick(() => {
                        this.stopTimer()
                        this.elapsedTime = 0
                    })
            }
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
    }
}

3.5.3 1.4.3 柯里化与偏函数

// 1. 柯里化 - 将多参数函数转换为单参数函数链
function curry<T extends Function>(fn: Function): T {
    return function curried(...args: Object[]): Function {
        if (args.length >= fn.length) {
            return fn.apply(this, args)
        }
        return function (...moreArgs: Object[]): Function {
            return curried.apply(this, args.concat(moreArgs))
        }
    } as T
}

// 示例
function add(a: number, b: number, c: number): number {
    return a + b + c
}

let curriedAdd = curry<(x: number) => (y: number) => (z: number) => number>(add)
console.log(curriedAdd(1)(2)(3))  // 6

// 2. 偏函数 - 固定部分参数
function createLogger(
    prefix: string
): (level: string, message: string) => void {
    return (level: string, message: string): void => {
        console.log(`[${prefix}] [${level}] ${message}`)
    }
}

let appLogger = createLogger("MyApp")
appLogger("INFO", "应用启动")     // [MyApp] [INFO] 应用启动
appLogger("ERROR", "发生错误")    // [MyApp] [ERROR] 发生错误

// 3. 实际应用:配置化组件
interface ComponentConfig {
    theme: string
    fontSize: number
    padding: number
}

function createStyledComponent(defaultConfig: ComponentConfig) {
    return (overrides: Partial<ComponentConfig>): ComponentConfig => {
        return {
            ...defaultConfig,
            ...overrides
        }
    }
}

let defaultTheme = createStyledComponent({
    theme: "light",
    fontSize: 14,
    padding: 16
})

// 创建特定场景的配置
let compactConfig: ComponentConfig = defaultTheme({ fontSize: 12, padding: 8 })
let largeConfig: ComponentConfig = defaultTheme({ fontSize: 18, padding: 24 })

3.5.4 1.4.4 不可变数据模式

// 1. 使用readonly创建不可变类型
interface ReadonlyPoint {
    readonly x: number
    readonly y: number
}

let point: ReadonlyPoint = { x: 10, y: 20 }
// point.x = 30  // 编译错误!只读属性不能修改

// 2. 不可变数据操作 - 返回新对象而非修改原对象
class ImmutableList<T> {
    private readonly items: ReadonlyArray<T>

    constructor(items: T[] = []) {
        this.items = [...items]
    }

    // 添加元素返回新实例
    add(item: T): ImmutableList<T> {
        return new ImmutableList([...this.items, item])
    }

    // 删除元素返回新实例
    remove(index: number): ImmutableList<T> {
        let newItems: T[] = [...this.items]
        newItems.splice(index, 1)
        return new ImmutableList(newItems)
    }

    // 更新元素返回新实例
    update(index: number, item: T): ImmutableList<T> {
        let newItems: T[] = [...this.items]
        newItems[index] = item
        return new ImmutableList(newItems)
    }

    get(index: number): T | undefined {
        return this.items[index]
    }

    get size(): number {
        return this.items.length
    }

    toArray(): T[] {
        return [...this.items]
    }
}

// 使用不可变列表
let list1 = new ImmutableList<number>([1, 2, 3])
let list2 = list1.add(4)  // 新实例
let list3 = list2.update(0, 10)  // 新实例

console.log(list1.toArray())  // [1, 2, 3] - 原列表不变
console.log(list2.toArray())  // [1, 2, 3, 4]
console.log(list3.toArray())  // [10, 2, 3, 4]

// 3. 不可变数据在状态管理中的应用
interface AppState {
    readonly users: ReadonlyArray<string>
    readonly loading: boolean
    readonly error: string | null
}

// 纯函数更新状态
function addUser(state: AppState, user: string): AppState {
    return {
        ...state,
        users: [...state.users, user]
    }
}

function setLoading(state: AppState, loading: boolean): AppState {
    return { ...state, loading }
}

function setError(state: AppState, error: string | null): AppState {
    return { ...state, error }
}

// 状态变更历史 - 利用不可变性实现时间旅行
class StateHistory<S> {
    private history: S[] = []
    private currentIndex: number = -1

    push(state: S): void {
        // 丢弃当前索引之后的历史
        this.history = this.history.slice(0, this.currentIndex + 1)
        this.history.push(state)
        this.currentIndex = this.history.length - 1
    }

    undo(): S | undefined {
        if (this.currentIndex > 0) {
            this.currentIndex--
            return this.history[this.currentIndex]
        }
        return undefined
    }

    redo(): S | undefined {
        if (this.currentIndex < this.history.length - 1) {
            this.currentIndex++
            return this.history[this.currentIndex]
        }
        return undefined
    }

    current(): S | undefined {
        return this.history[this.currentIndex]
    }
}

3.6 1.5 模块系统与工程化

3.6.1 1.5.1 ES Module规范

// 1. 命名导出
// math/Calculator.ts
export function add(a: number, b: number): number {
    return a + b
}

export function subtract(a: number, b: number): number {
    return a - b
}

export const PI: number = 3.14159265358979

// 2. 默认导出
// models/UserModel.ts
export default class UserModel {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }

    greet(): string {
        return `你好,我是${this.name}`
    }
}

// 3. 导入方式
// 命名导入
import { add, subtract, PI } from './math/Calculator'

// 默认导入
import UserModel from './models/UserModel'

// 命名空间导入
import * as MathUtils from './math/Calculator'
let result: number = MathUtils.add(1, 2)

// 4. 重命名导入导出
import { add as addition, subtract as subtraction } from './math/Calculator'

// 5. 重新导出
// utils/index.ts
export { add, subtract } from './math/Calculator'
export { default as UserModel } from './models/UserModel'
export * from './types'

// 6. 模块组织最佳实践
// services/ApiService.ts
export interface ApiConfig {
    baseUrl: string
    timeout: number
    headers: Map<string, string>
}

export class ApiService {
    private config: ApiConfig

    constructor(config: ApiConfig) {
        this.config = config
    }

    async get<T>(path: string): Promise<T> {
        let url: string = `${this.config.baseUrl}${path}`
        // ... 实现GET请求
        return {} as T
    }

    async post<T>(path: string, data: Object): Promise<T> {
        let url: string = `${this.config.baseUrl}${path}`
        // ... 实现POST请求
        return {} as T
    }
}

// 创建工厂函数
export function createApiService(
    baseUrl: string,
    timeout: number = 5000
): ApiService {
    let headers = new Map<string, string>()
    headers.set("Content-Type", "application/json")
    return new ApiService({ baseUrl, timeout, headers })
}

3.6.2 1.5.2 循环依赖处理

// 循环依赖问题示例与解决方案

// 问题场景:
// A.ts 导入 B.ts,B.ts 又导入 A.ts -> 循环依赖

// 解决方案1:提取共享接口到独立模块
// types/SharedTypes.ts
export interface NodeData {
    id: string
    name: string
}

export interface NodeProcessor {
    process(node: NodeData): void
}

// A.ts
import { NodeData, NodeProcessor } from './types/SharedTypes'

export class NodeA implements NodeProcessor {
    process(node: NodeData): void {
        console.log(`NodeA处理: ${node.name}`)
    }
}

// B.ts
import { NodeData, NodeProcessor } from './types/SharedTypes'

export class NodeB implements NodeProcessor {
    process(node: NodeData): void {
        console.log(`NodeB处理: ${node.name}`)
    }
}

// 解决方案2:依赖注入
// 定义接口
export interface ServiceA {
    doSomething(): void
}

export interface ServiceB {
    doAnother(): void
}

// 通过注入解决循环依赖
export class ServiceAImpl implements ServiceA {
    private serviceB: ServiceB | null = null

    setServiceB(serviceB: ServiceB): void {
        this.serviceB = serviceB
    }

    doSomething(): void {
        console.log("ServiceA执行")
        this.serviceB?.doAnother()
    }
}

export class ServiceBImpl implements ServiceB {
    private serviceA: ServiceA | null = null

    setServiceA(serviceA: ServiceA): void {
        this.serviceA = serviceA
    }

    doAnother(): void {
        console.log("ServiceB执行")
    }
}

3.6.3 1.5.3 动态导入

// 1. 动态导入 - 按需加载模块
async function loadFeatureModule(featureName: string): Promise<void> {
    switch (featureName) {
        case 'analytics':
            let analytics = await import('./features/AnalyticsModule')
            analytics.initialize()
            break
        case 'payment':
            let payment = await import('./features/PaymentModule')
            payment.setup()
            break
        default:
            console.log(`未知功能: ${featureName}`)
    }
}

// 2. 条件加载
async function loadPlatformSpecific(): Promise<Object> {
    let platform: string = 'default'
    // 根据平台动态加载
    let module = await import(`./platform/${platform}`)
    return module
}

// 3. 错误边界的动态导入
async function safeLoadModule(modulePath: string): Promise<Object | null> {
    try {
        let module = await import(modulePath)
        return module
    } catch (error) {
        console.error(`模块加载失败: ${modulePath}`, error)
        return null
    }
}

3.6.4 1.5.4 包管理与版本控制

// oh-package.json5 配置示例
/*
{
    "name": "my-harmony-app",
    "version": "1.0.0",
    "description": "HarmonyOS应用",
    "main": "",
    "author": "",
    "license": "Apache-2.0",
    "dependencies": {
        // 精确版本
        "@ohos/axios": "2.1.0",
        // 兼容版本范围
        "@ohos/lottie": "^1.0.0",
        // 本地模块引用
        "my-library": "file:./libs/my-library"
    },
    "devDependencies": {
        "@ohos/hypium": "1.0.6"
    }
}
*/

// 版本管理最佳实践
// 1. 语义化版本控制 (SemVer)
// major.minor.patch
// 1.0.0 -> 1.0.1 (修复bug)
// 1.0.0 -> 1.1.0 (新增功能,向后兼容)
// 1.0.0 -> 2.0.0 (破坏性变更)

// 2. 锁文件管理
// oh-package-lock.json 记录精确版本
// 确保团队成员和CI环境使用相同版本

// 3. 本地HAR包管理
// 创建HAR包
// build-profile.json5中配置:
/*
{
    "modules": [
        {
            "name": "entry",
            "srcPath": "./entry",
            "targets": [
                {
                    "name": "default",
                    "applyToProducts": ["default"]
                }
            ]
        },
        {
            "name": "common",
            "srcPath": "./common",
            "targets": [
                {
                    "name": "default",
                    "applyToProducts": ["default"]
                }
            ]
        }
    ]
}
*/

3.7 1.6 错误处理与调试

3.7.1 1.6.1 try-catch-finally高级用法

// 1. 结构化错误处理
class Result<T> {
    private constructor(
        private readonly value: T | null,
        private readonly error: Error | null,
        private readonly isSuccess: boolean
    ) {}

    static success<T>(value: T): Result<T> {
        return new Result<T>(value, null, true)
    }

    static failure<T>(error: Error): Result<T> {
        return new Result<T>(null, error, false)
    }

    get Value(): T {
        if (!this.isSuccess || this.value === null) {
            throw new Error("尝试获取失败结果的值")
        }
        return this.value
    }

    get Error(): Error {
        if (this.isSuccess || this.error === null) {
            throw new Error("尝试获取成功结果的错误")
        }
        return this.error
    }

    get IsSuccess(): boolean {
        return this.isSuccess
    }

    map<U>(fn: (value: T) => U): Result<U> {
        if (this.isSuccess && this.value !== null) {
            return Result.success(fn(this.value))
        }
        return Result.failure<U>(this.error!)
    }

    flatMap<U>(fn: (value: T) => Result<U>): Result<U> {
        if (this.isSuccess && this.value !== null) {
            return fn(this.value)
        }
        return Result.failure<U>(this.error!)
    }
}

// 使用Result模式
function parseJson(jsonString: string): Result<Object> {
    try {
        let parsed: Object = JSON.parse(jsonString)
        return Result.success(parsed)
    } catch (error) {
        return Result.failure(new Error(`JSON解析失败: ${(error as Error).message}`))
    }
}

let result: Result<Object> = parseJson('{"name": "张三"}')
if (result.IsSuccess) {
    console.log("解析成功:", result.Value)
} else {
    console.log("解析失败:", result.Error.message)
}

// 2. 资源清理模式
class ResourceHandler {
    async withResource<T>(
        acquire: () => Promise<T>,
        use: (resource: T) => Promise<void>,
        release: (resource: T) => Promise<void>
    ): Promise<void> {
        let resource: T | null = null
        try {
            resource = await acquire()
            await use(resource)
        } catch (error) {
            console.error("资源使用出错:", error)
            throw error
        } finally {
            if (resource !== null) {
                try {
                    await release(resource)
                } catch (releaseError) {
                    console.error("资源释放失败:", releaseError)
                }
            }
        }
    }
}

// 3. 多重异常捕获
async function robustFetch(url: string): Promise<string> {
    try {
        let response = await fetch(url)
        if (!response.ok) {
            throw new Error(`HTTP错误: ${response.status}`)
        }
        return await response.text()
    } catch (error) {
        if (error instanceof TypeError) {
            // 网络错误
            throw new Error(`网络连接失败: ${url}`)
        } else if (error instanceof Error) {
            // 其他已知错误
            throw error
        } else {
            // 未知错误
            throw new Error(`未知错误: ${String(error)}`)
        }
    }
}

3.7.2 1.6.2 自定义异常类

// 1. 异常层次结构
class AppError extends Error {
    code: number
    timestamp: number
    context: Map<string, string>

    constructor(message: string, code: number, context?: Map<string, string>) {
        super(message)
        this.name = "AppError"
        this.code = code
        this.timestamp = Date.now()
        this.context = context ?? new Map<string, string>()
    }

    toJSON(): Object {
        return {
            name: this.name,
            message: this.message,
            code: this.code,
            timestamp: this.timestamp,
            context: Object.fromEntries(this.context)
        }
    }
}

class NetworkError extends AppError {
    url: string
    statusCode: number

    constructor(message: string, url: string, statusCode: number) {
        super(message, 1001)
        this.name = "NetworkError"
        this.url = url
        this.statusCode = statusCode
    }
}

class ValidationError extends AppError {
    field: string
    constraint: string

    constructor(message: string, field: string, constraint: string) {
        super(message, 2001)
        this.name = "ValidationError"
        this.field = field
        this.constraint = constraint
    }
}

class AuthenticationError extends AppError {
    constructor(message: string) {
        super(message, 3001)
        this.name = "AuthenticationError"
    }
}

class AuthorizationError extends AppError {
    requiredPermission: string

    constructor(message: string, requiredPermission: string) {
        super(message, 3002)
        this.name = "AuthorizationError"
        this.requiredPermission = requiredPermission
    }
}

// 2. 错误处理服务
class ErrorHandlingService {
    private static instance: ErrorHandlingService | null = null

    static getInstance(): ErrorHandlingService {
        if (!ErrorHandlingService.instance) {
            ErrorHandlingService.instance = new ErrorHandlingService()
        }
        return ErrorHandlingService.instance
    }

    handleError(error: unknown): void {
        if (error instanceof NetworkError) {
            this.handleNetworkError(error)
        } else if (error instanceof ValidationError) {
            this.handleValidationError(error)
        } else if (error instanceof AuthenticationError) {
            this.handleAuthError(error)
        } else if (error instanceof AppError) {
            this.handleAppError(error)
        } else {
            this.handleUnknownError(error)
        }
    }

    private handleNetworkError(error: NetworkError): void {
        console.error(`网络错误 [${error.statusCode}]: ${error.message}`)
        console.error(`URL: ${error.url}`)
        // 显示网络错误提示
    }

    private handleValidationError(error: ValidationError): void {
        console.error(`验证错误 [${error.field}]: ${error.message}`)
        console.error(`约束: ${error.constraint}`)
        // 高亮错误字段
    }

    private handleAuthError(error: AuthenticationError): void {
        console.error(`认证错误: ${error.message}`)
        // 跳转到登录页
    }

    private handleAppError(error: AppError): void {
        console.error(`应用错误 [${error.code}]: ${error.message}`)
    }

    private handleUnknownError(error: unknown): void {
        console.error("未知错误:", error)
    }
}

3.7.3 1.6.3 全局异常捕获

// 1. 应用级全局异常处理
// EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
import { hilog } from '@kit.PerformanceAnalysisKit'

export default class EntryAbility extends UIAbility {
    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        hilog.info(0x0000, 'EntryAbility', '应用创建')

        // 注册全局异常处理
        this.registerGlobalErrorHandler()
    }

    private registerGlobalErrorHandler(): void {
        // 捕获未处理的Promise异常
        // 注意:ArkTS中通过context.getApplicationContext()获取应用上下文
        let appContext = this.context.getApplicationContext()

        // 注册应用级别错误回调
        appContext.on('applicationState', {
            onApplicationForeground: () => {
                hilog.info(0x0000, 'EntryAbility', '应用进入前台')
            },
            onApplicationBackground: () => {
                hilog.info(0x0000, 'EntryAbility', '应用进入后台')
            }
        })
    }

    onWindowStageCreate(windowStage: window.WindowStage): void {
        // 设置UI异常处理
        windowStage.on('windowStageEvent', (event: number) => {
            hilog.info(0x0000, 'EntryAbility', `窗口事件: ${event}`)
        })

        windowStage.loadContent('pages/Index', (err) => {
            if (err.code) {
                hilog.error(0x0000, 'EntryAbility',
                    '加载页面失败: %{public}s', JSON.stringify(err))
                return
            }
            hilog.info(0x0000, 'EntryAbility', '页面加载成功')
        })
    }
}

// 2. 错误日志收集器
class ErrorCollector {
    private static errors: Array<{
        error: string,
        timestamp: number,
        stack?: string
    }> = []
    private static maxSize: number = 100

    static collect(error: unknown): void {
        let errorInfo: string
        let stack: string | undefined

        if (error instanceof Error) {
            errorInfo = error.message
            stack = error.stack
        } else {
            errorInfo = String(error)
        }

        ErrorCollector.errors.push({
            error: errorInfo,
            timestamp: Date.now(),
            stack: stack
        })

        // 限制收集数量
        if (ErrorCollector.errors.length > ErrorCollector.maxSize) {
            ErrorCollector.errors.shift()
        }

        // 上报到远程服务器
        ErrorCollector.reportToServer(errorInfo, stack)
    }

    private static reportToServer(error: string, stack?: string): void {
        // 实际项目中实现错误上报
        console.log(`上报错误: ${error}`)
    }

    static getRecentErrors(count: number = 10): Array<Object> {
        return ErrorCollector.errors.slice(-count)
    }

    static clear(): void {
        ErrorCollector.errors = []
    }
}

3.7.4 1.6.4 调试技巧与工具

// 1. 自定义调试工具
class DebugHelper {
    // 性能计时
    static measure<T>(label: string, fn: () => T): T {
        let start: number = Date.now()
        let result: T = fn()
        let end: number = Date.now()
        console.log(`[性能] ${label}: ${end - start}ms`)
        return result
    }

    // 异步性能计时
    static async measureAsync<T>(
        label: string,
        fn: () => Promise<T>
    ): Promise<T> {
        let start: number = Date.now()
        let result: T = await fn()
        let end: number = Date.now()
        console.log(`[性能] ${label}: ${end - start}ms`)
        return result
    }

    // 数据快照
    static snapshot(label: string, data: Object): void {
        console.log(`[快照] ${label}:`)
        console.log(JSON.stringify(data, null, 2))
    }

    // 条件断点(日志形式)
    static assert(condition: boolean, message: string): void {
        if (!condition) {
            console.error(`[断言失败] ${message}`)
            console.trace()  // 打印调用栈
        }
    }

    // 组件渲染追踪
    static traceRender(componentName: string, props: Object): void {
        console.log(`[渲染] ${componentName}:`, JSON.stringify(props))
    }
}

// 2. 使用hilog进行日志管理
import { hilog } from '@kit.PerformanceAnalysisKit'

class AppLogger {
    private static DOMAIN: number = 0x0001
    private static TAG: string = "MyApp"

    static debug(message: string, ...args: Object[]): void {
        hilog.debug(AppLogger.DOMAIN, AppLogger.TAG, message, ...args.map(String))
    }

    static info(message: string, ...args: Object[]): void {
        hilog.info(AppLogger.DOMAIN, AppLogger.TAG, message, ...args.map(String))
    }

    static warn(message: string, ...args: Object[]): void {
        hilog.warn(AppLogger.DOMAIN, AppLogger.TAG, message, ...args.map(String))
    }

    static error(message: string, ...args: Object[]): void {
        hilog.error(AppLogger.DOMAIN, AppLogger.TAG, message, ...args.map(String))
    }
}

// 3. 组件调试技巧
@Component
struct DebuggableComponent {
    @State renderCount: number = 0
    @State debugInfo: string = ""

    aboutToAppear(): void {
        console.log(`[生命周期] DebuggableComponent aboutToAppear`)
    }

    aboutToReuse(params: Record<string, Object>): void {
        console.log(`[生命周期] DebuggableComponent aboutToReuse`)
    }

    aboutToDisappear(): void {
        console.log(`[生命周期] DebuggableComponent aboutToDisappear`)
    }

    build() {
        // 记录渲染次数
        this.renderCount++
        DebugHelper.traceRender("DebuggableComponent", {
            renderCount: this.renderCount
        })

        Column() {
            Text(`渲染次数: ${this.renderCount}`)
                .fontSize(16)
                .fontColor(this.renderCount > 5 ? '#FF0000' : '#000000')
            Text(this.debugInfo)
                .fontSize(12)
                .fontColor('#999999')
        }
    }
}

3.8 本章小结

本章深入介绍了ArkTS高级语法与编程范式,主要内容包括:

  1. ArkTS与TypeScript的关系:理解了ArkTS在TypeScript基础上的约束(禁用any、eval等)和扩展(声明式UI装饰器),掌握了更严格的静态类型检查机制。

  2. 高级类型系统:学习了联合类型、交叉类型、类型守卫、泛型约束、条件类型等高级类型特性,能够编写类型安全且高度复用的代码。

  3. 异步编程:掌握了Promise链式调用、async/await高级模式、并发控制(all/race/allSettled)以及TaskPool和Worker多线程方案。

  4. 函数式编程:理解了高阶函数、闭包、柯里化、偏函数和不可变数据模式,能够运用函数式思维解决实际问题。

  5. 模块系统:掌握了ES Module规范、循环依赖处理、动态导入和包管理最佳实践。

  6. 错误处理与调试:学习了结构化错误处理、自定义异常类层次、全局异常捕获和调试工具的使用。


3.9 练习题

3.9.1 一、单选题

1. 在ArkTS中,以下哪个特性是被禁止使用的?

A. 泛型 B. async/await C. any类型 D. 联合类型

答案:C

解析: ArkTS禁止使用any类型,这是与TypeScript的重要区别之一。ArkTS要求所有变量必须有明确的类型声明,不允许使用any作为”逃逸舱口”。泛型、async/await和联合类型在ArkTS中都是支持的。


2. 以下关于TaskPool和Worker的说法,正确的是?

A. TaskPool适合长期运行的后台任务 B. Worker适合短期计算密集型任务 C. TaskPool中的任务函数需要使用@Concurrent装饰器 D. Worker不能与主线程通信

答案:C

解析: TaskPool中的任务函数必须使用@Concurrent装饰器标记。TaskPool更适合短期、可并行化的计算任务;Worker更适合长期运行、需要维护状态的后台任务。Worker可以通过postMessage与主线程通信。


3. 在泛型约束 T extends HasLength 中,extends 关键字的含义是?

A. T继承HasLength B. T必须是HasLength的子类 C. T必须包含HasLength定义的所有属性 D. T就是HasLength类型

答案:C

解析: 在泛型约束中,extends 表示类型T必须满足HasLength接口所定义的约束,即T必须包含length属性。这不是传统意义上的继承,而是结构类型的约束。


3.9.2 二、多选题

4. 以下哪些是ArkTS中合法的异步编程模式?

A. Promise链式调用 B. async/await C. 回调函数 D. TaskPool并发

答案:A、B、C、D

解析: ArkTS支持所有标准的异步编程模式,包括Promise链式调用、async/await语法、传统的回调函数,以及HarmonyOS特有的TaskPool并发方案。开发者可以根据场景选择合适的异步模式。


5. 以下关于闭包的描述,正确的有哪些?

A. 闭包可以访问外部函数的局部变量 B. 闭包会导致被捕获的变量在外部函数返回后仍然存活 C. 闭包可能造成内存泄漏,需要谨慎使用 D. ArkTS禁止使用闭包

答案:A、B、C

解析: 闭包是函数式编程的核心概念。闭包可以捕获并记住其外部函数的作用域,即使外部函数已经返回。这既是闭包的强大之处,也可能导致内存问题,需要合理使用。ArkTS完全支持闭包。


3.9.3 三、判断题

6. ArkTS中的@Observed装饰器可以使类的属性变化被UI框架感知。

答案:正确

解析: @Observed装饰器标记的类,其属性变化会被ArkUI框架自动追踪,当属性值改变时,使用该属性的组件会自动重新渲染。这是HarmonyOS状态管理的基础机制之一。


7. Promise.allSettled()在任意一个Promise被reject时会立即返回。

答案:错误

解析: Promise.allSettled()会等待所有Promise都完成(无论fulfilled还是rejected),然后返回每个Promise的状态和结果。只有Promise.all()才会在任意一个Promise被reject时立即返回。Promise.race()则是返回最先完成的结果。


8. 在ArkTS中,可以使用as关键字进行任意类型之间的断言转换。

答案:错误

解析: ArkTS对类型断言有严格限制,不允许在完全不相关的类型之间进行断言转换。与TypeScript不同,ArkTS更倾向于使用类型守卫(typeof、instanceof等)来进行安全的类型收窄,而不是使用as断言。