B2B网络软件

标题: 多线程GET下载轮询等待工具 [打印本页]

作者: YYPOST群发软件    时间: 1 小时前
标题: 多线程GET下载轮询等待工具
多线程GET下载轮询等待工具
多线程GET下载轮询等待工具 B2B网络软件

多线程GET下载轮询等待工具 B2B网络软件

多线程GET下载轮询等待工具 B2B网络软件

多线程GET下载轮询等待工具 B2B网络软件

  1. /**
  2. * AIWROK 轮询等待工具 - 演示脚本(录屏版)
  3. * 故事线:模拟 APK 下载 → 等待文件生成 → 等待安装完成 → 成功启动
  4. *
  5. */

  6. importClass(java.lang.Thread);

  7. // ======================== 基础 ========================
  8. function doSleep(ms) { try { Thread.sleep(ms); } catch (e) {} }

  9. // 带节奏的打印:换行 + 延时
  10. function step(msg, delayMs) {
  11.     printl(msg);
  12.     doSleep(delayMs || 300);
  13. }

  14. function separator() {
  15.     printl("");
  16.     printl("──────────────────────────────────────────────────");
  17.     printl("");
  18. }

  19. // ======================== 通用轮询(核心) ========================
  20. /**
  21. * 轮询等待某个条件成立
  22. * @param {Function} condition  —— 每次返回 truthy 表示成立
  23. * @param {int} timeoutMs       —— 总超时(默认 10s)
  24. * @param {int} intervalMs      —— 轮询间隔(默认 200ms)
  25. * @param {String} label        —— 日志标签
  26. * @returns {Object} { success, waitedMs, lastValue, rounds }
  27. */
  28. function poll(condition, timeoutMs, intervalMs, label) {
  29.     timeoutMs  = timeoutMs  || 10000;
  30.     intervalMs = intervalMs || 200;
  31.     label      = label      || "轮询";

  32.     var start  = new Date().getTime();
  33.     var rounds = 0;
  34.     var lastVal = null;

  35.     while (true) {
  36.         lastVal = condition();
  37.         if (lastVal) {
  38.             var waited = new Date().getTime() - start;
  39.             printl("  ✅ [" + label + "] 条件达成!第 " + rounds + " 次轮询 · 耗时 " + waited + " ms");
  40.             return { success: true, waitedMs: waited, lastValue: lastVal, rounds: rounds };
  41.         }

  42.         // 每 5 次打一次进度(录屏看着不密不疏)
  43.         if (rounds % 5 === 0) {
  44.             var elapsed = rounds * intervalMs;
  45.             printl("  ⏳ [" + label + "] 等待中... 已轮询 " + rounds + " 次 · " + elapsed + " / " + timeoutMs + " ms");
  46.         }

  47.         if (new Date().getTime() - start >= timeoutMs) {
  48.             printl("  ❌ [" + label + "] 超时!(" + timeoutMs + " ms 内未达成)");
  49.             return { success: false, waitedMs: timeoutMs, lastValue: lastVal, rounds: rounds };
  50.         }

  51.         doSleep(intervalMs);
  52.         rounds++;
  53.     }
  54. }

  55. // ======================== 便捷方法 ========================

  56. /** 等待文件存在 */
  57. function waitForFile(path, timeoutMs, intervalMs) {
  58.     return poll(function() {
  59.         try { return new java.io.File(path).exists(); } catch (e) { return false; }
  60.     }, timeoutMs, intervalMs, "文件出现 " + path);
  61. }

  62. /** 等待文件大小 >= minBytes(模拟下载中) */
  63. function waitForFileSize(path, minBytes, timeoutMs, intervalMs) {
  64.     var label = "文件大小 ≥ " + minBytes + " 字节";
  65.     return poll(function() {
  66.         try {
  67.             var f = new java.io.File(path);
  68.             if (!f.exists()) return false;
  69.             var size = f.length();
  70.             // 顺便打印当前进度(录屏好看)
  71.             if (size > 0 && Math.random() < 0.3) {
  72.                 printl("     &#128229; 当前大小: " + size + " / " + minBytes + " 字节 " +
  73.                        Math.floor(size / minBytes * 100) + "%");
  74.             }
  75.             return size >= minBytes;
  76.         } catch (e) { return false; }
  77.     }, timeoutMs, intervalMs, label);
  78. }

  79. /** 等待 HTTP 200 */
  80. function waitForHttp(url, timeoutMs, intervalMs) {
  81.     return poll(function() {
  82.         try {
  83.             var res = http.get(url);
  84.             return res && res.code === 200;
  85.         } catch (e) { return false; }
  86.     }, timeoutMs, intervalMs, "接口 " + url);
  87. }

  88. /** 等待某条件返回 true,同时打印阶段标题 */
  89. function stage(title, condition, timeoutMs, intervalMs, label) {
  90.     printl("");
  91.     printl("  ▶ " + title);
  92.     // 造一条下划线(ES5 兼容)
  93.     var line = "  ";
  94.     for (var i = 0; i < title.length + 2; i++) line += "─";
  95.     printl(line);
  96.     return poll(condition, timeoutMs, intervalMs, label || title);
  97. }

  98. // ======================== 录屏演示 ========================
  99. function demo() {

  100.     // ══════════════════════════════════════════════════
  101.     //  开场
  102.     // ══════════════════════════════════════════════════
  103.     printl("╔══════════════════════════════════════════════╗");
  104.     printl("║                                              ║");
  105.     printl("║     &#128736;️  AIWROK sleep 轮询等待工具 演示       ║");
  106.     printl("║                                              ║");
  107.     printl("║     「模拟完整 APK 下载 → 安装流程」         ║");
  108.     printl("║                                              ║");
  109.     printl("╚══════════════════════════════════════════════╝");

  110.     doSleep(1200);   // 给录屏一个"标题定帧"时间

  111.     printl("");
  112.     printl("&#128214; 场景说明:");
  113.     printl("   我们将模拟一个完整的自动化流程 ——");
  114.     printl("   从服务器下载 APK 文件 → 等待写入磁盘 →");
  115.     printl("   等待文件大小达标 → 最后验证接口就绪。");
  116.     printl("");
  117.     printl("   用到的核心函数只有一个:poll()");
  118.     printl("   它负责:每隔 N ms 检查一次条件,");
  119.     printl("   条件成立立即返回,超时则返回失败。");
  120.     printl("");

  121.     doSleep(1500);

  122.     // ══════════════════════════════════════════════════
  123.     //  第一幕:后台线程模拟下载
  124.     // ══════════════════════════════════════════════════
  125.     separator();
  126.     printl("【第一幕】启动后台下载任务");
  127.     doSleep(800);

  128.     var apkPath = "/sdcard/Download/demo_app_v1.2.apk";
  129.     var targetSize = 4096;   // 模拟 4KB 的"APK"(实际写文字进去)

  130.     // 先清理残留
  131.     try { new java.io.File(apkPath).delete(); } catch (e) {}

  132.     step("&#128241; 目标 APK: " + apkPath, 500);
  133.     step("&#128230; 模拟大小: " + targetSize + " 字节", 500);
  134.     step("&#128640; 启动下载线程...", 800);

  135.     // 后台线程:分 4 次逐步写入文件(模拟渐进下载)
  136.     new thread().runJsCode(function() {
  137.         printl("     [后台] 连接服务器...");
  138.         doSleep(400);
  139.         printl("     [后台] 开始下载...");

  140.         var w = new java.io.FileWriter(apkPath);
  141.         var chunk = 1024;
  142.         var total = 0;

  143.         for (var i = 0; i < 4; i++) {
  144.             // 写 1KB:循环写单字符
  145.             var data = "";
  146.             for (var j = 0; j < chunk; j++) data += String.fromCharCode(65 + i);
  147.             w.write(data);
  148.             w.flush();
  149.             total += chunk;
  150.             printl("     [后台] 已写入 " + total + " / " + targetSize + " 字节");
  151.             doSleep(500);   // 故意慢一点,让轮询有东西可看
  152.         }
  153.         w.close();
  154.         printl("     [后台] ✅ 下载完成,文件已落盘");
  155.     }, "APK下载线程");

  156.     doSleep(800);   // 让后台线程先跑起来打一行

  157.     // ══════════════════════════════════════════════════
  158.     //  第二幕:轮询等待文件出现
  159.     // ══════════════════════════════════════════════════
  160.     separator();
  161.     printl("【第二幕】主线程轮询等待文件出现");
  162.     printl("   场景:后台在下载,主线程不能干等,");
  163.     printl("         需要时刻盯着文件是否已创建。");
  164.     doSleep(1000);

  165.     var r1 = stage("等待 APK 文件出现...", function() {
  166.         try { return new java.io.File(apkPath).exists(); } catch (e) { return false; }
  167.     }, 5000, 200, "waitForFile");

  168.     if (r1.success) {
  169.         step("&#128194; 文件已在磁盘上!耗时 " + r1.waitedMs + " ms", 600);
  170.     } else {
  171.         step("❌ 文件迟迟没出现,下载可能卡住了", 600);
  172.     }

  173.     doSleep(1000);

  174.     // ══════════════════════════════════════════════════
  175.     //  第三幕:轮询等待文件大小达标
  176.     // ══════════════════════════════════════════════════
  177.     separator();
  178.     printl("【第三幕】继续等 —— 文件大小达标才算下载完成");
  179.     printl("   场景:文件虽然创建了,但可能只写了一半。");
  180.     printl("         需要等大小 ≥ 期望值,才能开始安装。");
  181.     doSleep(1000);

  182.     var r2 = waitForFileSize(apkPath, targetSize, 8000, 300);

  183.     if (r2.success) {
  184.         step("&#128202; 文件大小达标!已完整写入 " + targetSize + " 字节", 600);
  185.     }

  186.     doSleep(1000);

  187.     // ══════════════════════════════════════════════════
  188.     //  第四幕:演示超时场景(等一个不存在的东西)
  189.     // ══════════════════════════════════════════════════
  190.     separator();
  191.     printl("【第四幕】演示:条件永远不成立 → 触发超时");
  192.     printl("   场景:实际业务中经常遇到 ——");
  193.     printl("         网络断了、接口挂了、权限没给...");
  194.     printl("         poll() 不会无限等,到点就返回 false。");
  195.     doSleep(1200);

  196.     var fakePath = "/sdcard/this_file_never_exists.xyz";
  197.     step("&#128269; 去等一个不存在的文件: " + fakePath, 600);
  198.     step("⏱️ 超时设为 1.5 秒,间隔 300 ms", 600);

  199.     var r3 = waitForFile(fakePath, 1500, 300);

  200.     step("&#128221; poll() 返回值: { success: " + r3.success + ", waitedMs: " + r3.waitedMs + " }", 800);
  201.     step("&#128161; 业务代码里可以这样写:", 400);
  202.     printl("      var r = waitForFile(xxx, 5000);");
  203.     printl("      if (!r.success) { printl(\"下载超时,重试或报错\"); }");

  204.     doSleep(1200);

  205.     // ══════════════════════════════════════════════════
  206.     //  第五幕:自定义条件 —— 组合使用
  207.     // ══════════════════════════════════════════════════
  208.     separator();
  209.     printl("【第五幕】自定义条件 & 组合使用");
  210.     printl("   poll() 的第一个参数是任意函数 ——");
  211.     printl("   想等啥就写啥,完全不挑。");
  212.     doSleep(1000);

  213.     // 演示:等文件出现 AND 大小达标(合并条件)
  214.     step("&#127919; 示例:等「文件存在 AND 大小 ≥ 80%」—— 一条 poll 搞定", 800);

  215.     var r4 = poll(function() {
  216.         try {
  217.             var f = new java.io.File(apkPath);
  218.             if (!f.exists()) return false;
  219.             return f.length() >= targetSize * 0.8;
  220.         } catch (e) { return false; }
  221.     }, 5000, 200, "文件存在 + 大小 ≥ 80%");

  222.     if (r4.success) {
  223.         step("&#127882; 两条条件同时满足!文件已准备好安装", 800);
  224.     }

  225.     doSleep(1200);

  226.     // ══════════════════════════════════════════════════
  227.     //  收尾
  228.     // ══════════════════════════════════════════════════
  229.     separator();

  230.     printl("╔══════════════════════════════════════════════╗");
  231.     printl("║                                              ║");
  232.     printl("║   ✨ 演示总结                                 ║");
  233.     printl("║                                              ║");
  234.     printl("║   poll(condition, timeout, interval, label)  ║");
  235.     printl("║                                              ║");
  236.     printl("║   · 想等控件? → waitForView()                ║");
  237.     printl("║   · 想等文字? → waitForText()                ║");
  238.     printl("║   · 想等文件? → waitForFile()                ║");
  239.     printl("║   · 想等接口? → waitForHttp()                ║");
  240.     printl("║   · 想等啥都行 → poll(function(){ ... })      ║");
  241.     printl("║                                              ║");
  242.     printl("╚══════════════════════════════════════════════╝");

  243.     doSleep(2000);

  244.     // 清理
  245.     try { new java.io.File(apkPath).delete(); } catch (e) {}

  246.     printl("");
  247.     printl("&#127916; 演示结束,感谢观看!");
  248. }

  249. demo();

复制代码







欢迎光临 B2B网络软件 (http://bbs.niubt.cn/) Powered by Discuz! X3.2