YYPOST群发软件 发表于 2026-6-22 07:25:13

AIWROK软件定时检查页面状态防止卡死技巧

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;
      
      // 开始步骤
      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();


页: [1]
查看完整版本: AIWROK软件定时检查页面状态防止卡死技巧