HarmonyOS 7 AppStartup依赖不执行:先查循环依赖,再查任务耗时

HarmonyOS 7 AppStartup依赖不执行:先查循环依赖,再查任务耗时
任务A等待B,B又等待A,两个任务都没有真正开始。只看启动耗时会误以为设备很慢,实际上依赖图本身无解。这里用拓扑排序在执行前发现环,同时发现拼错的依赖名。
适配范围
拓扑合法不代表启动够快,也不代表所有任务都应阻塞首屏。它只检查依赖关系。接入AppStartup时对照当前配置格式提取任务名与依赖,并在构建检查或测试阶段执行;示例不是替代系统调度器。
案例一
config、db、view顺序依赖:输出合法顺序,重复依赖不会造成额外等待。
案例二
a与b相互等待:执行前直接报cycle;依赖名不存在则报missing,避免直到启动现场才发现。
可以运行的实现
export function startupOrder(tasks) {
const names = Object.keys(tasks), ready = [], result = [];
const pending = new Map(names.map(n=>[n,new Set(tasks[n])]));
for(const [name,deps] of pending)for(const dep of deps)if(!pending.has(dep))throw Error('missing:'+dep);
for(const [name,deps] of pending)if(!deps.size)ready.push(name);
while(ready.length){const name=ready.shift();result.push(name);pending.delete(name);for(const [n,deps] of pending){deps.delete(name);if(!deps.size&&!ready.includes(n))ready.push(n);}}
if(pending.size)throw Error('cycle:'+[...pending.keys()].join(','));
return result;
}
复现与断言
把实现与以下测试放进同一个example.mjs,执行node example.mjs。断言失败会报错,全部通过正常退出。这些断言已经在本地Node.js执行;它们不代表SDK编译、真机接口调用或性能实测已经通过。
import assert from 'node:assert/strict';
assert.deepEqual(startupOrder({config:[],db:['config'],view:['db']}),['config','db','view']);
assert.throws(()=>startupOrder({a:['b'],b:['a']}),/cycle/);
assert.throws(()=>startupOrder({a:['missing']}),/missing/);
assert.deepEqual(startupOrder({}),[]);
assert.deepEqual(startupOrder({a:[],b:['a','a']}),['a','b']);
方案取舍
每个任务自己等Promise,容易把依赖结构藏在实现里。执行前检查图能给出明确阻塞集合。示例报出的集合可能包含依赖环的下游任务,不声称它精确等于环节点;需要精确环路径时再加入DFS定位。
接入时别漏掉这些边界
拓扑合法不代表启动够快,也不代表所有任务都应阻塞首屏。它只检查依赖关系。接入AppStartup时对照当前配置格式提取任务名与依赖,并在构建检查或测试阶段执行;示例不是替代系统调度器。
复用时把输入获取与纯逻辑分开:界面、系统事件和服务请求负责取得真实输入,独立模块负责给出判断或保存状态。保留上述两个案例作为回归测试,并对失败原因记录最少必要日志,不记录文件内容、账号凭据或其它敏感数据。升级SDK后重新核对支持设备、接口版本与错误行为,而不是只改目标版本号。
官方资料
示例验证环境为Node.js,验证范围是应用侧逻辑。本文不将示例当作系统接口接入代码;具体接口的支持设备、最低版本和调用方式,以所用SDK对应的官方文档为准。
更多推荐
所有评论(0)