Appearance
ArkTS 异步编程
async/await、Promise、回调是 ArkTS 异步编程的核心。理解它们的区别和使用场景,是避免主线程卡顿的关键。
1. 异步编程的发展
回调 → Promise → async/awaitArkTS 支持所有三种方式,推荐顺序:async/await > Promise > 回调
2. Promise
2.1 基本用法
typescript
// 创建 Promise
const promise = new Promise<string>((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
resolve('Hello')
}, 1000)
})
// 处理结果
promise.then((value) => {
console.log(value) // "Hello"
}).catch((error) => {
console.error(error)
}).finally(() => {
console.log('完成')
})2.2 Promise 链式调用
typescript
// ✅ 链式调用(避免回调地狱)
getUser()
.then((user) => {
return getUserPosts(user.id)
})
.then((posts) => {
return getPostDetail(posts[0].id)
})
.then((detail) => {
console.log(detail)
})
.catch((error) => {
console.error('请求失败:', error)
})2.3 Promise 的状态
| 状态 | 含义 | 转换 |
|---|---|---|
| Pending(等待) | 初始状态 | - |
| Fulfilled(成功) | 操作完成 | Pending → Fulfilled |
| Rejected(失败) | 操作失败 | Pending → Rejected |
⚠️ 一旦状态确定,就无法再改变。
3. async/await
3.1 基本用法
typescript
// async 函数返回 Promise
async function fetchData(): Promise<string> {
const response = await http.get('/api/data')
return response.body
}
// await 只能在 async 函数中使用
async function process() {
const data = await fetchData() // 等待完成
console.log(data)
}3.2 对比:Promise vs async/await
typescript
// ❌ Promise 链式(可读性差)
getUser()
.then((user) => {
return getOrders(user.id)
})
.then((orders) => {
return getOrderDetail(orders[0].id)
})
.then((detail) => {
console.log(detail)
showDetail(detail)
})
.catch((error) => {
console.error(error)
})
// ✅ async/await(更清晰)
async function processDetail() {
try {
const user = await getUser()
const orders = await getOrders(user.id)
const detail = await getOrderDetail(orders[0].id)
showDetail(detail)
} catch (error) {
console.error(error)
}
}4. Promise.all — 并发请求
typescript
// 并发请求(并行执行,总时间 = 最慢的那个)
async function loadDashboard() {
const [users, orders, stats] = await Promise.all([
http.get('/api/users').then(r => r.json()),
http.get('/api/orders').then(r => r.json()),
http.get('/api/stats').then(r => r.json())
])
return { users, orders, stats }
}
// 对比:串行请求(总时间 = 所有时间之和)
async function loadDashboardSerial() {
const users = await http.get('/api/users').then(r => r.json())
const orders = await http.get('/api/orders').then(r => r.json())
const stats = await http.get('/api/stats').then(r => r.json())
return { users, orders, stats }
}5. 错误处理
5.1 try/catch
typescript
async function safeFetch(url: string) {
try {
const response = await http.get(url)
if (response.statusCode !== 200) {
throw new Error(`HTTP ${response.statusCode}`)
}
return response.json()
} catch (error) {
console.error('请求失败:', error)
// 返回默认值或重试
return getDefaultData()
}
}5.2 Promise.allSettled — 部分失败不中断
typescript
// 所有请求都执行,不管成功失败
async function loadAll() {
const results = await Promise.allSettled([
http.get('/api/users'),
http.get('/api/orders'),
http.get('/api/stats')
])
// 逐个处理结果
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`请求 ${index} 成功:`, result.value)
} else {
console.log(`请求 ${index} 失败:`, result.reason)
}
})
}6. 异步编程的陷阱
6.1 主线程卡顿
typescript
@Component
struct Index {
@State data: string = ''
// ❌ 错误:同步操作放在主线程
onLoad() {
const result = this.synchronousWork() // 耗时操作!
this.data = result
}
// ✅ 正确:异步处理 + TaskPool
async onLoadCorrect() {
// 先更新 UI
this.data = '加载中...'
// 后台处理
const result = await TaskPool.execute(() => {
return this.synchronousWork()
})
this.data = result
}
}6.2 await 在 build 中
typescript
// ❌ 错误:build 中不能 await
@Component
struct Index {
@State data: string = ''
build() {
// ❌ 编译错误!build 中不能写 await
this.data = await fetchData()
Text(this.data)
}
}
// ✅ 正确:在生命周期或回调中处理
@Component
struct Index {
@State data: string = ''
aboutToAppear() {
fetchData().then((d) => {
this.data = d // 在异步回调中修改 @State
})
}
build() {
Text(this.data)
}
}7. 面试高频考点
Q1: Promise.all 和 Promise.allSettled 的区别?
回答:
Promise.all:任一请求失败,全部中断,返回错误Promise.allSettled:所有请求都执行完,无论成败,返回每个请求的结果
Q2: async/await 相比 Promise 链式调用的优势?
回答:代码更清晰可读,错误处理用 try/catch 更符合直觉,变量可以直接使用不需要在每个 then 中重新获取。
Q3: 主线程卡顿的常见原因?
回答:在 aboutToAppear 或点击事件中进行同步 I/O 操作、复杂 JSON 解析或大量计算。解决方法:用 async/await 放到后台、用 TaskPool 处理耗时任务。
🐱 小猫提示:异步编程记住三个要点——async/await 优先、Promise.all 并行、build 中不能 await。这是高频考点。