HarmonyOS 鸿蒙Next中怎样在应用中使用异步编程提高性能?

HarmonyOS 鸿蒙Next中怎样在应用中使用异步编程提高性能? 开发中需要处理异步操作问题:

  • 数据库查询
  • 网络请求
  • 文件读写
  • 多个异步操作协调
3 回复

解决方案

1. 基础Promise使用

/**
 * Promise基础
 */
function loadData(): Promise<Item[]> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' }
      ];
      
      // ✅ 成功时调用resolve
      resolve(data);
      
      // ❌ 失败时调用reject
      // reject(new Error('加载失败'));
    }, 1000);
  });
}

// ✅ 使用Promise
loadData()
  .then(data => {
    console.info('加载成功:', data.length);
  })
  .catch(err => {
    console.error('加载失败:', err);
  })
  .finally(() => {
    console.info('加载完成');
  });

2. async/await语法

/**
 * async/await简化异步代码
 */
@Component
struct DataPage {
  @State items: Item[] = [];
  @State isLoading: boolean = false;
  
  async aboutToAppear(): Promise<void> {
    await this.loadData();
  }
  
  async loadData(): Promise<void> {
    this.isLoading = true;
    
    try {
      // ✅ await等待Promise完成
      const items = await ItemDao.findAll();
      this.items = items;
      
    } catch (err) {
      console.error('加载失败:', err);
      promptAction.showToast({ message: '加载失败' });
      
    } finally {
      this.isLoading = false;
    }
  }
  
  build() {
    if (this.isLoading) {
      LoadingProgress();
    } else {
      List() {
        ForEach(this.items, (item: Item) => {
          ListItem() {
            Text(item.name);
          }
        })
      }
    }
  }
}

3. 并发执行

/**
 * Promise.all: 并发执行,全部完成
 */
async function loadAllData(): Promise<void> {
  try {
    // ✅ 并发执行3个请求
    const [items, categories, tags] = await Promise.all([
      ItemDao.findAll(),
      CategoryDao.findAll(),
      TagDao.findAll()
    ]);
    
    console.info('全部加载完成');
    console.info('物品数量:', items.length);
    console.info('分类数量:', categories.length);
    console.info('标签数量:', tags.length);
    
  } catch (err) {
    // ❌ 任何一个失败都会进入catch
    console.error('加载失败:', err);
  }
}

/**
 * Promise.allSettled: 等待全部完成(无论成功失败)
 */
async function loadDataSafely(): Promise<void> {
  const results = await Promise.allSettled([
    ItemDao.findAll(),
    CategoryDao.findAll(),
    TagDao.findAll()
  ]);
  
  results.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      console.info(`第${index + 1}个请求成功:`, result.value.length);
    } else {
      console.error(`第${index + 1}个请求失败:`, result.reason);
    }
  });
}

4. 竞速执行

/**
 * Promise.race: 返回最快完成的
 */
async function loadWithTimeout(): Promise<Item[]> {
  // ✅ 设置5秒超时
  const timeout = new Promise<Item[]>((_, reject) => {
    setTimeout(() => {
      reject(new Error('请求超时'));
    }, 5000);
  });
  
  // ✅ 竞速:谁先完成返回谁
  return await Promise.race([
    ItemDao.findAll(),  // 实际请求
    timeout             // 超时控制
  ]);
}

5. 顺序执行

/**
 * 顺序执行多个异步操作
 */
async function sequentialOperations(): Promise<void> {
  // ✅ 顺序执行
  const item = await ItemDao.findById(1);
  const category = await CategoryDao.findById(item.categoryId);
  const tags = await TagDao.findByItemId(item.id);
  
  console.info('物品:', item.name);
  console.info('分类:', category.name);
  console.info('标签:', tags.length);
}

/**
 * 批量顺序执行
 */
async function batchSequential(ids: number[]): Promise<Item[]> {
  const items: Item[] = [];
  
  // ✅ for...of 顺序执行
  for (const id of ids) {
    const item = await ItemDao.findById(id);
    items.push(item);
    
    // 每次查询间隔100ms
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return items;
}

6. 错误处理最佳实践

/**
 * 完整的错误处理
 */
@Component
struct SafeDataPage {
  @State items: Item[] = [];
  @State error: string = '';
  @State isLoading: boolean = false;
  
  async loadData(): Promise<void> {
    this.isLoading = true;
    this.error = '';
    
    try {
      // ✅ 主要逻辑
      const items = await ItemDao.findAll();
      
      if (items.length === 0) {
        throw new Error('暂无数据');
      }
      
      this.items = items;
      
    } catch (err) {
      // ✅ 错误分类处理
      if (err instanceof Error) {
        this.error = err.message;
      } else {
        this.error = '未知错误';
      }
      
      console.error('加载失败:', err);
      
    } finally {
      // ✅ 无论成功失败都执行
      this.isLoading = false;
    }
  }
  
  build() {
    Column() {
      if (this.isLoading) {
        LoadingProgress();
      } else if (this.error) {
        Text(this.error).fontColor(Color.Red);
      } else {
        List() {
          ForEach(this.items, (item: Item) => {
            ListItem() {
              Text(item.name);
            }
          })
        }
      }
    }
  }
}

7. 实战案例

/**
 * 保存数据并更新UI
 */
@Component
struct ItemEditPage {
  @State isSaving: boolean = false;
  private item: Item = new Item();
  
  async onSave(): Promise<void> {
    if (this.isSaving) {
      return;  // 防止重复提交
    }
    
    this.isSaving = true;
    
    try {
      // ✅ 1. 验证数据
      this.validateData();
      
      // ✅ 2. 保存到数据库
      const itemId = await ItemDao.insert(this.item);
      
      // ✅ 3. 更新卡片
      await FormDataService.getInstance().updateAllForms();
      
      // ✅ 4. 提示成功
      promptAction.showToast({ message: '保存成功' });
      
      // ✅ 5. 返回上一页
      router.back();
      
    } catch (err) {
      // ❌ 错误处理
      let message = '保存失败';
      
      if (err instanceof Error) {
        if (err.message.includes('UNIQUE')) {
          message = '名称已存在';
        } else {
          message = err.message;
        }
      }
      
      promptAction.showToast({ message });
      
    } finally {
      this.isSaving = false;
    }
  }
  
  validateData(): void {
    if (!this.item.name) {
      throw new Error('请输入名称');
    }
    
    if (this.item.name.length > 100) {
      throw new Error('名称不能超过100字');
    }
  }
  
  build() {
    Column() {
      Button('保存')
        .enabled(!this.isSaving)
        .onClick(() => {
          this.onSave();
        })
    }
  }
}

关键要点

1. Promise状态

// Pending(进行中) → Fulfilled(成功) 或 Rejected(失败)

const promise = new Promise((resolve, reject) => {
  // 成功
  resolve(data);
  
  // 失败
  reject(error);
});

2. async/await规则

// ✅ async函数返回Promise
async function getData(): Promise<Item[]> {
  return await ItemDao.findAll();
}

// ✅ await只能在async函数中使用
async function loadData(): Promise<void> {
  const data = await getData();  // ✅
}

// ❌ 错误:非async函数中使用await
function loadData(): void {
  const data = await getData();  // ❌ 编译错误
}

3. 错误传播

async function a(): Promise<void> {
  throw new Error('错误A');
}

async function b(): Promise<void> {
  await a();  // ✅ 错误会向上传播
}

async function c(): Promise<void> {
  try {
    await b();  // ✅ 可以在这里捕获错误A
  } catch (err) {
    console.error('捕获到错误:', err);
  }
}

最佳实践

1. 总是处理错误

// ✅ 推荐:使用try-catch
async function loadData(): Promise<void> {
  try {
    const data = await getData();
  } catch (err) {
    console.error(err);
  }
}

// ❌ 不推荐:忽略错误
async function loadData(): Promise<void> {
  const data = await getData();  // 错误会导致Promise rejected
}

2. 避免回调地狱

// ❌ 回调地狱
loadData((data) => {
  processData(data, (result) => {
    saveData(result, () => {
      console.info('完成');
    });
  });
});

// ✅ 使用async/await
async function process(): Promise<void> {
  const data = await loadData();
  const result = await processData(data);
  await saveData(result);
  console.info('完成');
}

3. 合理使用并发

// ✅ 可以并发的操作
const [items, categories] = await Promise.all([
  loadItems(),
  loadCategories()
]);

// ❌ 必须顺序执行的操作
const user = await loadUser();
const profile = await loadProfile(user.id);  // 依赖user

性能对比

场景 顺序执行 并发执行
3个独立请求 3s 1s
5个独立请求 5s 1s
性能提升 - 80%+

总结

异步编程要点:

✅ 使用async/await简化代码 ✅ Promise.all并发执行 ✅ try-catch处理错误 ✅ finally清理资源 ✅ 避免阻塞主线程

掌握异步编程,代码更简洁高效

更多关于HarmonyOS 鸿蒙Next中怎样在应用中使用异步编程提高性能?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用异步编程提高性能主要通过TaskPool和Worker模块实现。TaskPool适用于轻量级任务,支持任务派发和结果返回。Worker用于耗时操作,在独立线程中运行以避免阻塞主线程。开发者可使用Promise或async/await语法处理异步操作,确保UI流畅。例如,通过TaskPool执行计算密集型任务,或利用Worker处理网络请求和文件读写。

在HarmonyOS Next中,使用异步编程提升应用性能的核心是充分利用其基于ArkTS/ArkUI的并发模型,避免阻塞UI线程。主要手段包括使用Promiseasync/await语法以及TaskPool(任务池)。

1. 处理I/O密集型异步操作(网络、数据库、文件)

对于你提到的数据库查询、网络请求和文件读写,这些都属于I/O密集型任务。最佳实践是使用async/await语法配合返回Promise的API,使代码逻辑清晰,避免回调地狱。

  • 网络请求:使用@ohos.net.http模块,其方法(如http.createHttp().request)本身是异步的。在async函数内使用await调用,UI线程就不会被阻塞。
    async function fetchData(url: string): Promise<void> {
      try {
        let response = await http.createHttp().request(url, { method: http.RequestMethod.GET });
        console.info('Result:', response.result);
        // 更新UI(ArkUI框架会自动处理线程安全)
      } catch (error) {
        console.error('Request failed:', error);
      }
    }
    
  • 数据库/文件操作@ohos.data.relationalStore(关系型数据库)和@ohos.file.fs(文件系统)的关键API也提供了基于Promise的异步接口。务必在async函数中使用await调用,例如await store.query(...)await fs.readText(...)

2. 处理CPU密集型异步操作与多任务协调

当需要执行计算密集型任务(如图像处理、复杂算法)或协调多个异步操作时,为了不阻塞UI线程,应使用TaskPool

  • 使用TaskPool:它是轻量级线程池,适用于耗时计算。将函数派发到任务池执行,返回一个Promise

    import taskpool from '@ohos.taskpool';
    
    @Concurrent
    function computeHeavyTask(data: number): number {
      // 执行复杂计算
      return data * data;
    }
    
    async function runTask(): Promise<void> {
      let task = new taskpool.Task(computeHeavyTask, 100);
      let result = await taskpool.execute(task); // 在任务池异步执行
      console.info('Result:', result);
      // 更新UI
    }
    

    注意:传递给TaskPool的函数必须用@Concurrent装饰器标记,且参数和返回值需支持序列化。

  • 协调多个异步操作

    • 并行执行:使用Promise.all(),当所有异步操作完成时继续。
    async function parallelTasks(): Promise<void> {
      let [dbResult, fileResult] = await Promise.all([
        queryDatabase(),
        readFileContent()
      ]);
      // 两者都完成后处理
    }
    
    • 串行/链式执行:直接使用await顺序调用,或使用Promise链。

3. 关键原则与性能要点

  • UI线程唯一:所有UI更新必须在主线程(UI线程)进行。异步操作获取数据后,在async函数中直接更新状态变量(如@State装饰的变量),ArkUI框架会确保UI更新是线程安全的。
  • 合理选择工具:I/O等待型任务用async/await;纯CPU计算型任务,特别是耗时的,用TaskPool
  • 避免阻塞:绝对不要在UI线程上执行同步的耗时操作(如大规模循环计算、同步网络请求)。这会导致应用界面“卡死”。
  • 错误处理:务必用try...catch包裹await调用,或为Promise添加.catch(),以妥善处理异步错误。

通过将数据库、网络、文件等阻塞性操作异步化,并将CPU密集型任务卸载到TaskPool,可以显著提升应用的响应速度与流畅度,这是HarmonyOS Next开发中优化性能的基础手段。

回到顶部