一、前言:告别JS/TS陋习,建立ArkTS工程化编程思维
在鸿蒙开发中,绝大多数闪退、接口报错、逻辑异常、内存隐患,都源于函数不规范、异步写法混乱、异常不捕获、流程控制随意。
很多前端开发者沿用松散的JS/TS写法:参数不定义、异步嵌套地狱、异常裸奔、循环逻辑不严谨,在静态强类型的ArkTS体系下,极易出现编译报错、隐性Bug、页面渲染异常等问题。
本文一站式吃透 ArkTS完整函数体系、默认参数/剩余参数、高阶函数封装、条件循环流程控制、Promise/async&await异步全机制、try/catch工程化异常捕获规范,所有代码均为鸿蒙原生可直接运行的标准写法,适配项目开发、组件封装、网络请求、业务逻辑落地。
二、ArkTS函数完整体系(强类型规范)
ArkTS摒弃JS动态弱类型特性,强制函数参数、返回值类型可控,杜绝隐式类型转换、空值逃逸,是业务逻辑稳定的核心基础。
1. 基础函数定义规范
ArkTS工程强制规范:简单函数可类型推导,业务函数必须显式声明参数与返回值类型,无返回值统一使用 void。
// 标准规范:带参数类型 + 返回值类型
function add(a: number, b: number): number {
return a + b;
}
// 无返回值函数
function printLog(msg: string): void {
console.log("日志:", msg);
}
// 空参函数
function getAppVersion(): string {
return "1.0.0";
}
2. 可选参数
通过 ? 定义可选参数,可选参数必须放在必选参数后方,适配参数非必传业务场景。
// age 为可选参数
function getUserInfo(name: string, age?: number): string {
if (age) {
return `姓名:${name},年龄:${age}`;
}
return `姓名:${name},年龄未知`;
}
// 调用支持两种传参方式
getUserInfo("鸿蒙开发者");
getUserInfo("鸿蒙开发者", 25);
3. 默认参数(工程高频)
默认参数可替代大量空值判断逻辑,参数未传参/传undefined时自动生效,简化容错代码,提升代码简洁度。
// 带默认参数:分页默认第1页、每页10条
function getPageList(page: number = 1, size: number = 10): void {
console.log("请求页码:", page, "条数:", size);
}
getPageList(); // 默认 1、10
getPageList(2); // 2、10
getPageList(3, 20); // 3、20
规范要点:默认参数优先级高于可选参数,无需额外写 undefined 兜底。
4. 剩余参数 Rest(不定长参数)
ArkTS 严格约束剩余参数规则:仅能作为函数最后一个参数、类型必须为数组,用于接收不定数量的同类型参数,适配批量计算、批量传参场景。
// 不定长数字求和
function sum(...numbers: number[]): number {
let total = 0;
for (let n of numbers) {
total += n;
}
return total;
}
console.log(sum()); // 0
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20)); // 30
核心禁忌:剩余参数后禁止拼接其他参数,禁止混合不同类型数据。
三、高阶函数封装实战(ArkTS工程化核心)
高阶函数指参数为函数、返回值为函数的函数,是鸿蒙工具封装、接口拦截、防抖节流、通用逻辑抽离的核心能力,配合泛型可实现绝对类型安全。
1. 基础高阶函数(函数作为参数)
// 通用数组遍历高阶函数
function arrForEach<T>(arr: T[], callback: (item: T, index: number) => void): void {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}
// 调用
let strArr: string[] = ["鸿蒙", "ArkTS", "HarmonyOS"];
arrForEach(strArr, (item, index) => {
console.log(index, item);
});
2. 高阶函数返回函数(防抖实战)
业务高频场景:搜索框输入、按钮防重复点击,通过高阶函数封装通用防抖逻辑,全局复用。
// 通用防抖封装
function debounce(fn: () => void, delay: number) {
let timer: number | null = null;
return function() {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn();
}, delay);
}
}
// 业务使用
const search = debounce(() => {
console.log("执行搜索请求");
}, 500);
四、条件与循环流程控制(ArkTS严格规范)
ArkTS 延续标准流程控制语法,但强类型校验+严格语法约束,杜绝JS隐式转换漏洞,适配业务判断、数据遍历场景。
1. 条件判断 if / else if / else
禁止隐式布尔转换,判断条件必须精准,空值、零值、空字符串需显式判断。
let score: number = 85;
if (score >= 90) {
console.log("优秀");
} else if (score >= 60) {
console.log("及格");
} else {
console.log("不及格");
}
2. 多分支 switch 规范
适配枚举、固定状态判断,必须写 break 防止穿透,复杂状态优先使用switch而非多层if。
enum OrderStatus { PENDING, PAYED, FINISH, CANCEL }
let status: OrderStatus = OrderStatus.PENDING;
switch (status) {
case OrderStatus.PENDING:
console.log("待支付");
break;
case OrderStatus.PAYED:
console.log("已支付");
break;
case OrderStatus.FINISH:
console.log("已完成");
break;
case OrderStatus.CANCEL:
console.log("已取消");
break;
default:
console.log("未知状态");
}
3. 三大循环规范
for 循环:精准下标遍历(适配复杂逻辑)
for (let i = 0; i < 5; i++) {
console.log("下标:", i);
}
for...of 循环:遍历数组/字符串(工程首选)
let list: string[] = ["A", "B", "C"];
for (let item of list) {
console.log("元素:", item);
}
while / do...while 循环:条件循环
let num: number = 0;
while (num < 3) {
console.log(num);
num++;
}
五、ArkTS异步编程全解:Promise完整机制
鸿蒙网络请求、本地存储、动画延时、线程任务均为异步操作,Promise是异步编程的底层核心,彻底解决回调地狱问题,是async/await的基础。
1. Promise三种状态(不可逆)
- pending:进行中(初始状态)
- fulfilled:成功完成(触发then)
- rejected:失败异常(触发catch)
状态一旦从pending变更为成功/失败,永久不可逆。
2. Promise基础封装(模拟接口请求)
// 封装通用异步请求
function requestData(): Promise<string> {
return new Promise((resolve, reject) => {
// 模拟网络延时
setTimeout(() => {
let isSuccess = true;
if (isSuccess) {
resolve("接口请求成功,返回数据");
} else {
reject(new Error("接口请求失败"));
}
}, 1000);
});
}
// 链式调用
requestData().then(res => {
console.log(res);
}).catch(err => {
console.log(err.message);
}).finally(() => {
console.log("请求结束,无论成败都会执行");
});
3. Promise常用静态方法
// 1. Promise.all:所有请求成功才返回,任意一个失败直接失败
Promise.all([requestData(), requestData()])
// 2. Promise.race:谁先完成返回谁
Promise.race([requestData(), requestData()])
// 3. Promise.resolve / reject:快速创建Promise
Promise.resolve("成功数据");
Promise.reject(new Error("自定义异常"));
六、async/await 终极异步方案(鸿蒙工程首选)
async/await 是Promise的语法糖,将异步代码转为同步写法,代码可读性极强,是鸿蒙项目网络请求、异步业务的统一规范写法。
1. 核心语法规则
- 函数前加
async标识异步函数,返回值自动包装为Promise await只能在async函数内部使用- await会阻塞当前异步流程,等待Promise状态变更后继续执行
2. 标准实战写法
// 异步函数
async function loadData() {
try {
// 等待异步请求完成
let res = await requestData();
console.log("拿到异步结果:", res);
} catch (err) {
console.log("异步请求异常:", err);
}
}
// 调用异步函数
loadData();
3. 连续异步串行请求(业务高频)
// 先请求用户信息,再请求用户列表
async function loadUserPage() {
try {
await requestData();
await requestData();
console.log("所有请求执行完毕");
} catch (err) {
console.log("请求异常");
}
}
七、ArkTS try/catch 异常捕获工程规范(杜绝闪退)
ArkTS作为编译型强类型语言,编译期可拦截大部分错误,但运行时异常、异步异常、接口数据异常、类型转换异常必须通过try/catch捕获,否则会导致页面白屏、应用闪退、未捕获异常报错。
1. 基础语法结构
try {
// 可能报错的风险代码
let str: string = null as unknown as string;
str.length;
} catch (err) {
// 捕获异常,兜底容错
console.log("捕获运行时异常:", err);
} finally {
// 无论是否报错,必然执行(释放资源、关闭加载弹窗)
console.log("执行收尾操作");
}
2. 四大必须加try/catch的业务场景
- 所有await异步请求:网络超时、接口报错、数据为空必捕获
- 数据解析、类型转换:JSON解析、强类型断言容错
- 本地存储、文件读写:权限不足、文件不存在异常
- 复杂计算、递归逻辑:数值溢出、死循环报错兜底
3. 异步异常核心规范(重点避坑)
ArkTS中裸奔的async函数异常不会崩溃进程,但会产生unhandledRejection 未捕获异常,造成隐性业务异常,所有await必须包裹try/catch。
// 工程标准异步模板
async function safeRequest() {
try {
let res = await requestData();
// 正常业务逻辑
} catch (error) {
// 统一异常处理:弹窗提示、日志上报、容错兜底
console.error("异步业务异常:", error);
}
}
八、高频踩坑与工程落地规范总结
1. 函数参数规范
- 默认参数、可选参数后置,剩余参数必须为最后一个参数
- 禁止无类型函数,业务函数必须显式声明参数、返回值类型
- 不定长参数统一使用剩余参数,摒弃arguments动态取值
2. 高阶函数规范
- 通用工具高阶函数必须搭配泛型,保证类型安全
- 防抖、节流、遍历封装统一抽离全局工具,避免代码冗余
3. 异步编程规范
- 杜绝Promise嵌套地狱,优先使用async/await同步化写法
- 所有异步请求强制try/catch捕获,禁止异常裸奔
- 并发场景优先使用Promise.all,提升请求效率
4. 流程与异常规范
- switch语句必须写break,防止状态穿透
- 循环内部避免频繁创建函数、对象,优化内存性能
- finally仅用于资源释放,禁止写业务逻辑、修改返回值