ArkTS-异步与命名空间
异步
同步和异步的区别
同步:按顺序,一件一件事做
异步:不等前一件事做完,可以先做后面的事

异步操作
异步操作是不阻塞主线程、允许程序非阻塞式并发处理多个任务的执行模式。
function loadText(): string {
console.log('文字加载完成');
return 'ArkTS';
}
//同步方法模拟加载图片
function loadImage(): Uint8Array {
let start = Data.now();
while (Data.now() – start < 2000) {}
let imageBuffer = new Uint8Array();
console.log('图片加载完成');
return imageBuffer;
}
//异步方法模拟加载图片()
function asyncLoadImage(callback: (imageBuffer: Uint8Array)
=> void): void {
//定时器,ArkTS内置的异步函数,2000ms后执行回调
setTimeout(() => {
let imageBuffer = new Uint8Array();
callback(imageBuffer);
}, 2000);
}
注意此处定时器的用法
| 同步 | loadText(); loadImage();console.log(‘显示网页’) | 文字加载完成图片加载完成显示网页 |
| 异步 | loadText();asyncLoadImage((result) => { console.log(‘图片加载完成’);});console.log(‘显示网页’); | 文字加载完成显示网页图片加载完成 |
Promise
异步编程的核心挑战是处理操作完成后的结果
Promise是专门用于处理异步操作的对象,用于封装需延迟执行的任务。
以下为Promise的状态:当异步逻辑成功或失败时,Promise的状态也也会随之改变
| pending | 初始状态(等待中) | 异步操作未完成 |
| fulfilled | 成功状态(已完成) | 异步操作顺利执行 |
| rejected | 失败状态(已拒绝) | 异步操作出错 |
//封装异步操作
new Promise((resolve, reject)
=> {
异步逻辑
成功调用resolve传结果
失败调用reject传错误
})
处理结果:
.then(处理成功)
.catch(处理失败)
代码示例:
const loadImagePromise: Promise<string> = new Promise((resolve, reject) => {
setTimeout(() => {
let success = true;
if (success) {
resolve('图片加载完成');
} else {
reject(new Error('图片加载失败'));
}
}, 2000);
})
loadImagePromise
.then((result) => {
console.log('success:', result);
})
.catch((error: Error) => {
console.log('failed:', error.message);
})
async/await
设想这么一个场景:
当多个异步方法之间存在异步关系时,想按顺序执行这些异步函数,当用封装函数嵌套使用。不便于理解代码
//用Promise封装异步操作
function loadImage(): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
let success = true;
if (success) {
resolve('图片加载完成');
} else {
reject(new Error('图片加载失败'));
}
}, 2000);
});
}
//嵌套使用,一层套一层,不方便书写也不方便阅读代码
loadImage()
.then(() => {
loadImage()
.then(() => {
loadImage(…)
})
})
以async与await配合使用可以将异步操作以同步代码的风格实现:
async function loadPage(): Promise<void> {
await loadImage();
await loadImage();
await loadImage();
}
xxxxxxxxxx function printInfo(value: string): void;fucntion printInfo(value: number): void;function printInfo(value: string | number): void { if (typeof value === ‘string’) { //typeof: 返回后方变量的类型 console.log(‘文字信息:’, value); } else { console.log(‘数字信息:’, value); }}javascript
用try/catch捕获异步操作的异常(代替Promise的catch()方法)
async function loadWebPage(): Promise<void> {
console.log('文字加载完成');
try {
let result = await loadImage();
console.log(result);
console.log('显示网页');
} catch(error){
console.error(`error: ${(error as Error).message}`);
}
}
loadWebPage();
/*输出:
*文字加载完成
*图片加载完成
*显示网页
*/
命名空间
静态import
模块的导入与导出
模块是代码拆分、复用与隔阂的核心机制——将复杂项目按功能/业务拆分成多个独立文件(每个文件就是一个模块),通过export暴露模块内的接口、类、函数,再通过import在其他模块中导入使用。

命名导出与导入
直接在成员声明前加export,可导出多个成员(包括类、常量、函数、接口),导入时需用同名接收。

导入命名导出的成员:用import {成员名1,成员名2} from “模块路径“,成员名必须和导出时一致,可通过as重命名。

默认导入与导出
一个模块只能由一个默认导出,使用export default声明。导入时可以自定义名称 ,无需与导出名称一致。默认导出适合模块的核心功能,例如模块只暴露一个类。

导入默认导出的成员:用import 自定义名称 from ”模块路径”,名称自定义,无需和导出时一致。

动态import
大多数情况下静态导入就能满足写代码时的绝大多数情况,但是某些特殊情况下,用静态导入就不是很合适了,比如:
- 导入的模块太大,直接静态导入,会让代码加载速度变慢
- 要导入的模块一开始不存在,需要等一段时间。比如从网络上获取才能使用。
动态import是ArkTS中用汉语按需加载模块的核心机制,会返回Promise对象并以异步方式实现模块的条件加载和运行时解耦,适用于性能优化和复杂业务场景。
import('../module/Light')
.then((lightImport) => {
lightImport.createDefault('light');
console.log(`${lightImport.DEFAULT_BRIGHTNESS}`);
})
.catch((error: BusinessError) => {
console.log(`error ${error.code} ${error.message}`);
});
命名空间的概念和使用
命名空间是通过namespace关键字定义的代码逻辑边界,用于将相关类、接口、函数等组织在一起,避免命名冲突并提高篇代码可维护性。其结构形如下图:

详细示例:
export namespace DeviceControl {
export class Device {
name: string = '';
}
export interface LightConfig {
name: string;
maxBrightness: number;
}
export function createDevice(): Device {
return new Device();
}
export const DEFAULT_BRIGHTNESS = 50;
}
通过export导出命名空间,以命名空间.成员名访问导出内容


