 | |  |  | AIWROK软件定时检查页面状态防止卡死技巧
- /**
- * AIWROK 脚本任务管理器 - 实用工具集
- *
- * 针对安卓自动化脚本开发的实际需求:
- * 1. 定时检查页面状态(防止卡死)
- * 2. 超时保护机制(避免无限等待)
- * 3. 任务重试机制(提高稳定性)
- * 4. 执行进度监控(方便调试)
- *
- * 这些都是写脚本时经常遇到的痛点!
- */
- // ==================== 核心工具类 ====================
- /**
- * 超时控制器
- * 解决:等待某个条件时,防止无限等待导致脚本卡死
- */
- function TimeoutController() {
- var timeoutId = null;
- var isCompleted = false;
-
- /**
- * 启动超时保护
- * @param {Number} timeoutMs - 超时时间(毫秒)
- * @param {Function} onTimeout - 超时回调
- * @returns {Object} 控制器对象
- */
- this.start = function(timeoutMs, onTimeout) {
- if (timeoutId !== null) {
- this.cancel();
- }
-
- isCompleted = false;
- var self = this;
-
- timeoutId = runTime.setTimeout(function() {
- if (!isCompleted) {
- print.log("[超时控制] ⚠ 操作超时!");
- if (onTimeout) {
- onTimeout();
- }
- }
- }, timeoutMs);
-
- print.log("[超时控制] ✓ 已启动超时保护 (" + timeoutMs + "ms)");
- return this;
- };
-
- /**
- * 标记完成(清除超时)
- */
- this.complete = function() {
- if (!isCompleted && timeoutId !== null) {
- runTime.stopTimeout(timeoutId);
- timeoutId = null;
- isCompleted = true;
- print.log("[超时控制] ✓ 操作完成,已取消超时保护");
- }
- return this;
- };
-
- /**
- * 取消超时保护
- */
- this.cancel = function() {
- if (timeoutId !== null) {
- runTime.stopTimeout(timeoutId);
- timeoutId = null;
- print.log("[超时控制] ✓ 已取消超时保护");
- }
- return this;
- };
- }
- /**
- * 重试控制器
- * 解决:网络请求、节点查找等可能失败的操作,自动重试
- */
- function RetryController() {
- var maxRetries = 3;
- var currentRetry = 0;
- var retryDelay = 2000; // 重试间隔(毫秒)
-
- /**
- * 配置重试参数
- * @param {Number} maxRetries - 最大重试次数
- * @param {Number} delay - 重试间隔(毫秒)
- */
- this.configure = function(maxRetries, delay) {
- this.maxRetries = maxRetries;
- this.retryDelay = delay || 2000;
- return this;
- };
-
- /**
- * 执行带重试的操作
- * @param {Function} operation - 要执行的操作(返回true表示成功)
- * @param {String} operationName - 操作名称(用于日志)
- * @param {Function} onSuccess - 成功回调
- * @param {Function} onFail - 失败回调
- */
- this.execute = function(operation, operationName, onSuccess, onFail) {
- currentRetry = 0;
- var self = this;
-
- function tryExecute() {
- currentRetry++;
- print.log("[重试控制] 尝试 " + operationName + " (第" + currentRetry + "/" + self.maxRetries + "次)");
-
- var success = operation();
-
- if (success) {
- print.log("[重试控制] ✓ " + operationName + " 成功!");
- if (onSuccess) {
- onSuccess();
- }
- } else {
- if (currentRetry < self.maxRetries) {
- print.log("[重试控制] ⚠ " + operationName + " 失败," +
- (self.retryDelay/1000) + "秒后重试...");
-
- runTime.setTimeout(function() {
- tryExecute();
- }, self.retryDelay);
- } else {
- print.log("[重试控制] ✗ " + operationName + " 失败,已达最大重试次数");
- if (onFail) {
- onFail();
- }
- }
- }
- }
-
- tryExecute();
- };
- }
- /**
- * 心跳检测器
- * 解决:长时间运行的脚本,定期检查是否还在正常工作
- */
- function HeartbeatMonitor() {
- var intervalId = null;
- var heartbeatCount = 0;
- var lastHeartbeatTime = null;
- var checkInterval = 5000; // 心跳间隔(毫秒)
-
- /**
- * 启动心跳监控
- * @param {Number} interval - 心跳间隔(毫秒)
- * @param {Function} onHeartbeat - 每次心跳的回调
- */
- this.start = function(interval, onHeartbeat) {
- if (interval) {
- checkInterval = interval;
- }
-
- heartbeatCount = 0;
- var self = this;
-
- intervalId = runTime.setInterval(function() {
- heartbeatCount++;
- lastHeartbeatTime = new Date();
-
- print.log("[心跳监控] ♥ 心跳 #" + heartbeatCount + " - " +
- lastHeartbeatTime.toLocaleTimeString());
-
- if (onHeartbeat) {
- onHeartbeat(heartbeatCount);
- }
- }, checkInterval);
-
- print.log("[心跳监控] ✓ 心跳监控已启动 (间隔:" + checkInterval + "ms)");
- return this;
- };
-
- /**
- * 停止心跳监控
- */
- this.stop = function() {
- if (intervalId !== null) {
- runTime.clearInterval(intervalId);
- intervalId = null;
- print.log("[心跳监控] ✓ 心跳监控已停止 (共" + heartbeatCount + "次)");
- }
- return this;
- };
-
- /**
- * 获取运行时长
- */
- this.getRunTime = function() {
- if (lastHeartbeatTime) {
- var now = new Date();
- return now - lastHeartbeatTime;
- }
- return 0;
- };
- }
- /**
- * 任务进度追踪器
- * 解决:多步骤任务,实时显示执行进度
- */
- function ProgressTracker() {
- var totalSteps = 0;
- var currentStep = 0;
- var stepNames = [];
- var startTime = null;
-
- /**
- * 初始化任务
- * @param {Array} steps - 步骤名称数组
- */
- this.init = function(steps) {
- stepNames = steps;
- totalSteps = steps.length;
- currentStep = 0;
- startTime = new Date();
-
- print.log("");
- print.log("========== 任务进度追踪 ==========");
- print.log("总步骤: " + totalSteps);
- print.log("步骤列表: " + steps.join(" → "));
- print.log("==================================");
- print.log("");
-
- return this;
- };
-
- /**
- * 更新进度
- * @param {String} stepName - 当前步骤名称
- * @param {String} status - 状态 (start/complete/error)
- */
- this.update = function(stepName, status) {
- if (status === "start") {
- currentStep++;
- var progress = Math.floor((currentStep / totalSteps) * 100);
- print.log("[进度 " + progress + "%] ▶ 开始: " + stepName);
- } else if (status === "complete") {
- print.log("[进度 " + Math.floor((currentStep / totalSteps) * 100) + "%] ✓ 完成: " + stepName);
- } else if (status === "error") {
- print.log("[进度 " + Math.floor((currentStep / totalSteps) * 100) + "%] ✗ 错误: " + stepName);
- }
-
- return this;
- };
-
- /**
- * 完成任务
- */
- this.finish = function() {
- var endTime = new Date();
- var duration = endTime - startTime;
-
- print.log("");
- print.log("========== 任务完成 ==========");
- print.log("总耗时: " + duration + "ms (" + (duration/1000).toFixed(2) + "秒)");
- print.log("完成步骤: " + currentStep + "/" + totalSteps);
- print.log("==============================");
- print.log("");
-
- return this;
- };
- }
- // ==================== 实用场景示例 ====================
- /**
- * 场景1:带超时保护的页面等待
- * 实际问题:等待某个元素出现,但不能无限等待
- */
- function example_WaitForElementWithTimeout() {
- print.log("");
- print.log("【场景1】带超时保护的页面等待");
- print.log("----------------------------------------");
-
- var timeoutCtrl = new TimeoutController();
-
- // 模拟等待某个元素出现
- timeoutCtrl.start(5000, function() {
- print.log("超时处理:元素未找到,执行备选方案");
- // 这里可以执行备选逻辑,比如刷新页面、点击其他按钮等
- });
-
- // 模拟查找元素的操作
- runTime.setTimeout(function() {
- // 假设找到了元素
- print.log("✓ 找到目标元素!");
- timeoutCtrl.complete(); // 标记完成,清除超时
-
- // 继续后续操作...
- }, 2000);
-
- sleep.second(秒=6);
- }
- /**
- * 场景2:带重试的网络请求
- * 实际问题:网络不稳定,请求可能失败,需要自动重试
- */
- function example_RetryNetworkRequest() {
- print.log("");
- print.log("【场景2】带重试的网络请求");
- print.log("----------------------------------------");
-
- var retryCtrl = new RetryController();
- retryCtrl.configure(3, 2000); // 最多重试3次,间隔2秒
-
- var attemptCount = 0;
-
- retryCtrl.execute(
- function() {
- // 模拟网络请求(前两次失败,第三次成功)
- attemptCount++;
- print.log(" 发起网络请求... (尝试#" + attemptCount + ")");
-
- if (attemptCount < 3) {
- print.log(" ✗ 请求失败:网络超时");
- return false;
- } else {
- print.log(" ✓ 请求成功!");
- return true;
- }
- },
- "数据上传",
- function() {
- // 成功回调
- print.log("→ 继续处理响应数据...");
- },
- function() {
- // 失败回调
- print.log("→ 所有重试都失败了,记录错误日志");
- }
- );
-
- sleep.second(秒=10);
- }
- /**
- * 场景3:后台任务心跳监控
- * 实际问题:长时间运行的脚本,需要确认它还在正常工作
- */
- function example_HeartbeatMonitoring() {
- print.log("");
- print.log("【场景3】后台任务心跳监控");
- print.log("----------------------------------------");
-
- var heartbeat = new HeartbeatMonitor();
-
- // 启动心跳监控
- heartbeat.start(3000, function(count) {
- // 每次心跳时可以执行一些检查
- if (count % 3 === 0) {
- print.log(" [定期自检] 内存正常、网络连接正常");
- }
- });
-
- // 模拟后台任务运行
- print.log("后台任务正在运行...");
- sleep.second(秒=10);
-
- // 停止心跳
- heartbeat.stop();
- }
- /**
- * 场景4:多步骤任务进度追踪
- * 实际问题:复杂的自动化流程,需要清楚知道执行到哪一步了
- */
- function example_ProgressTracking() {
- print.log("");
- print.log("【场景4】多步骤任务进度追踪");
- print.log("----------------------------------------");
-
- var tracker = new ProgressTracker();
-
- // 定义任务步骤
- tracker.init([
- "打开应用",
- "登录账号",
- "导航到目标页面",
- "执行数据采集",
- "保存数据",
- "退出应用"
- ]);
-
- // 模拟执行各个步骤
- var steps = [
- {name: "打开应用", delay: 1},
- {name: "登录账号", delay: 2},
- {name: "导航到目标页面", delay: 1},
- {name: "执行数据采集", delay: 3},
- {name: "保存数据", delay: 1},
- {name: "退出应用", delay: 1}
- ];
-
- for (var i = 0; i < steps.length; i++) {
- var step = steps[i];
-
- // 开始步骤
- tracker.update(step.name, "start");
-
- // 模拟步骤执行
- sleep.second(秒=step.delay);
-
- // 完成步骤
- tracker.update(step.name, "complete");
- }
-
- // 任务完成
- tracker.finish();
- }
- /**
- * 场景5:综合应用 - 完整的自动化流程
- * 结合所有工具,实现一个健壮的自动化脚本
- */
- function example_CompleteAutomation() {
- print.log("");
- print.log("【场景5】综合应用 - 完整的自动化流程");
- print.log("----------------------------------------");
- print.log("这个场景展示了如何组合使用所有工具");
- print.log("构建一个健壮、可靠的自动化脚本");
- print.log("");
-
- // 1. 进度追踪
- var tracker = new ProgressTracker();
- tracker.init(["初始化", "执行任务", "清理资源"]);
-
- // 2. 心跳监控(确保脚本不会卡死)
- var heartbeat = new HeartbeatMonitor();
- heartbeat.start(5000);
-
- // 步骤1:初始化
- tracker.update("初始化", "start");
-
- var timeoutCtrl = new TimeoutController();
- timeoutCtrl.start(3000, function() {
- print.log("初始化超时,使用默认配置");
- });
-
- sleep.second(秒=1);
- timeoutCtrl.complete();
- tracker.update("初始化", "complete");
-
- // 步骤2:执行任务(带重试)
- tracker.update("执行任务", "start");
-
- var retryCtrl = new RetryController();
- retryCtrl.configure(2, 1500);
-
- retryCtrl.execute(
- function() {
- print.log(" 执行核心任务...");
- return true; // 模拟成功
- },
- "核心任务",
- function() {
- print.log(" 任务执行成功");
- },
- function() {
- print.log(" 任务执行失败");
- }
- );
-
- sleep.second(秒=3);
- tracker.update("执行任务", "complete");
-
- // 步骤3:清理资源
- tracker.update("清理资源", "start");
-
- heartbeat.stop();
-
- sleep.second(秒=1);
- tracker.update("清理资源", "complete");
- tracker.finish();
-
- print.log("✓ 自动化流程完成!");
- }
- // ==================== 主演示流程 ====================
- function main() {
- print.log("╔════════════════════════════════════════╗");
- print.log("║ AIWROK 脚本任务管理器 - 实用工具集 ║");
- print.log("║ ║");
- print.log("║ 解决脚本开发的常见痛点: ║");
- print.log("║ • 防止无限等待导致卡死 ║");
- print.log("║ • 自动重试提高稳定性 ║");
- print.log("║ • 心跳监控确保正常运行 ║");
- print.log("║ • 进度追踪方便调试 ║");
- print.log("╚════════════════════════════════════════╝");
-
- sleep.second(秒=2);
-
- // 演示各个场景
- example_WaitForElementWithTimeout();
- example_RetryNetworkRequest();
- example_HeartbeatMonitoring();
- example_ProgressTracking();
- example_CompleteAutomation();
-
- print.log("");
- print.log("╔════════════════════════════════════════╗");
- print.log("║ 演示完成! ║");
- print.log("╚════════════════════════════════════════╝");
- print.log("");
- print.log("这些工具可以直接用到你的脚本中:");
- print.log("");
- print.log("1. TimeoutController - 超时保护");
- print.log(" 用途:等待元素、网络请求等操作的超时控制");
- print.log(" 示例:var tc = new TimeoutController();");
- print.log(" tc.start(5000, onTimeout);");
- print.log(" // ... 执行操作 ...");
- print.log(" tc.complete();");
- print.log("");
- print.log("2. RetryController - 自动重试");
- print.log(" 用途:网络请求、节点查找等可能失败的操作");
- print.log(" 示例:var rc = new RetryController();");
- print.log(" rc.configure(3, 2000);");
- print.log(" rc.execute(operation, '操作名', onSuccess, onFail);");
- print.log("");
- print.log("3. HeartbeatMonitor - 心跳监控");
- print.log(" 用途:长时间运行的脚本,定期检查是否正常");
- print.log(" 示例:var hb = new HeartbeatMonitor();");
- print.log(" hb.start(5000, onHeartbeat);");
- print.log(" // ... 运行任务 ...");
- print.log(" hb.stop();");
- print.log("");
- print.log("4. ProgressTracker - 进度追踪");
- print.log(" 用途:多步骤任务,实时显示执行进度");
- print.log(" 示例:var pt = new ProgressTracker();");
- print.log(" pt.init(['步骤1', '步骤2']);");
- print.log(" pt.update('步骤1', 'start');");
- print.log(" // ... 执行 ...");
- print.log(" pt.update('步骤1', 'complete');");
- print.log(" pt.finish();");
- print.log("");
- print.log("把这些类复制到你的脚本开头,就能直接使用了!");
- }
- // ==================== 执行入口 ====================
- main();
复制代码
| |  | |  |
|