【鸿蒙生态共建】一文讲清耗时操作对定时器的超时事件影响及解决方案-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利

定时器是研发过程中常用的 API,用于实现不希望代码立即运行,而是等待一段时间后再执行。例如在游戏开发中,可以使用定时器来控制游戏角色的动画播放速度和行动间隔;在数据同步场景中,可利用定时器定期检查并同步本地数据与服务器数据;在界面更新场景中,通过定时器定时刷新界面上的动态信息,如倒计时显示等。

但是,有一种情况下,会block定时器的调度,那就是在同一个函数中,启动了定时器后,在同一个线程执行了一个比较耗时的任务,这时该定时器还没有开始进行调度,会产生block,导致定时的操作没有按预期执行。

本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第9章内容的延续,是咱这本书读者的福利,在本篇内容中介绍定时器的基本写法及如书写不被block的定时器,欢迎大家一同来深入的了解,甚至可以当作面试题来学习。

对本书感兴趣的同学可以点击以下链接进行购买,或者了解我的班级参加 班级共同学习,点击链接可进入(华为官方活动)

​​​​

《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利博文目录,点击查看

1.定时器的基本写法

下面的示例实现了基本的定时器的写法,100毫秒后执行

复制代码
console.log("俩毛豆 测试定时器 start time");
setTimeout(()=>{
  console.log("俩毛豆 测试定时器 time out");
},100)
console.log("俩毛豆 测试定时器 调用完成");

上面的代码,执行日志如下图所示,可以看出,定时器调用完成的日志先输出,之后约100毫秒定时器时间到。

​2.增加长时任务

下面的示例在同一函数且同一线程内,调用定时器之后,增加一耗时1秒的任务。

复制代码
function longRunningFun() {
  console.log("俩毛豆 测试定时器 模拟耗时1秒开始");
  const startTime = new Date().getTime();
  while (new Date().getTime() - startTime < 1000) {
    // 空循环,模拟1秒耗时
  }
  console.log("俩毛豆 测试定时器 模拟耗时1秒结束");
}

console.log("俩毛豆 测试定时器 start time");
setTimeout(()=>{
  console.log("俩毛豆 测试定时器 time out");
},100)
longRunningFun();
console.log("俩毛豆 测试定时器 调用完成");

可以看出,耗时1秒的操作,影响了定时器的执行。

3.耗时操作使用异步的方式执行

下面的示例,将耗时的操作,使用异步的方式执行

复制代码
function longRunningFun() {
  console.log("俩毛豆 测试定时器 模拟耗时1秒开始");
  const startTime = new Date().getTime();
  while (new Date().getTime() - startTime < 1000) {
    // 空循环,模拟1秒耗时
  }
  console.log("俩毛豆 测试定时器 模拟耗时1秒结束");
}


async function  dolongRunningFunTask(): Promise<string> {
  return new Promise(resolve => {
    longRunningFun();
    resolve("")
  })
}

console.log("俩毛豆 测试定时器 start time");
setTimeout(()=>{
  console.log("俩毛豆 测试定时器 time out");
},100)
dolongRunningFunTask().then(()=>{
  console.log("俩毛豆 测试定时器 耗时任务执行完成 调用方收到事件");
});
console.log("俩毛豆 测试定时器 调用完成");

执行代码log如下图所示,可以看出,因为使用异步执行了耗时操作,定时器的超时时间,会在耗时操作之后(因为在同一个线程,且先被执行),但会在耗时操作执行完成后,立即执行(耗时操作1秒,定时器100毫秒)。

4.解决耗时操作对定时器的影响

从上面的示例代码可以看出,同一线程内的耗时操作会影响定时器的超时事件产生的时间的。如需要解决该问题,需要使用多线程的方式来执行耗时任务。

复制代码
@Concurrent
function longRunningFunConcurrent() {
  console.log("俩毛豆 测试定时器 Concurrent 模拟耗时1秒开始");
  const startTime = new Date().getTime();
  while (new Date().getTime() - startTime < 1000) {
    // 空循环,模拟1秒耗时
  }
  console.log("俩毛豆 测试定时器 Concurrent 模拟耗时1秒结束");
}

async function dolongRunningFunConcurrentTask(): Promise<string> {
  return new Promise(resolve => {
    const task: taskpool.Task = new taskpool.Task(longRunningFunConcurrent);
    taskpool.execute(task).then(() => {
      resolve("")
    })
  })
}
console.log("俩毛豆 测试定时器 start time");
setTimeout(()=>{
  console.log("俩毛豆 测试定时器 time out");
},100)
dolongRunningFunConcurrentTask().then(()=>{
  console.log("俩毛豆 测试定时器 执行完成 调用方收到事件");
});
console.log("俩毛豆 测试定时器 调用完成");

执行log如下图所示,可以看出,定时器超时的事件,并没有被耗时操作影响

5.总结

本文探讨了定时器在鸿蒙应用开发中的使用注意事项。通过示例代码展示了定时器的基本写法,以及同一线程内耗时操作对定时器执行的阻塞影响。文章提出了两种解决方案:一是将耗时操作改为异步执行,二是使用多线程技术(如taskpool)来执行耗时任务。实验结果表明,多线程方式能有效避免耗时操作对定时器的影响。本文内容节选自《精通HarmonyOSNEXT:鸿蒙App开发入门与项目化实战》一书,为读者提供了实用的定时器优化技巧。

对本书感兴趣的同学可以点击以下链接进行购买,或者了解我的班级参加 班级共同学习,点击链接可进入(华为官方活动)

相关推荐
周胡杰3 小时前
鸿蒙preferences单多例使用,本地存储类
缓存·华为·harmonyos·preferences·鸿蒙本地存储
IvanCodes3 小时前
[鸿蒙2025领航者闯关] 共享终端的隐形守护者:基于 HarmonyOS 6 的全链路隐私闭环实战
华为·harmonyos·鸿蒙
芒鸽8 小时前
鸿蒙PC上FFmpeg+Electron的Encode Smoke(P2) 排错实录:从“无法播放/时长为 0”到“保留画面且转完整时长”
ffmpeg·electron·harmonyos
2501_9444490810 小时前
帮助中心页面 Cordova&OpenHarmony 混合开发实战
harmonyos
航Hang*10 小时前
第二章:网络系统建设与运维(中级)——华为设备基本命令
运维·计算机网络·华为·ensp·交换机
北方的流星10 小时前
华为PPPoE协议的配置
运维·网络·华为
独自归家的兔11 小时前
基于 cosyvoice-v3-plus 的 个人音色复刻 (华为OBS)
人工智能·华为·语音识别
DARLING Zero two♡11 小时前
0-Day 极速响应:基于 vLLM-Ascend 在昇腾 NPU 上部署 Qwen2.5 的实战避坑指南
华为·gpu算力·vllm
北方的流星11 小时前
华为帧中继配置
运维·网络·华为
搬砖的kk11 小时前
在鸿蒙PC上开发鸿蒙应用:一场从协同到高效的技术之旅
华为·harmonyos