YYPOST群发软件 发表于 2026-9-8 06:35:11

AIWROK函数没定义就调用脚本直接崩

AIWROK函数没定义就调用脚本直接崩






// ============================================================================
//AIWROK 避坑案例 #02(可跑演示):新手最常踩的 5 个坑
// ============================================================================
//
//这个脚本有什么用?
//─────────────────
//新手刚接触 AIWROK 写脚本,90% 都会在这 5 个地方卡住:
//    1. 函数没定义就调用 → 脚本直接崩
//    2. 用 setTimeout → 找不到函数
//    3. 用 Java 网络类 → 报未定义
//    4. 开线程 → API 用错
//    5. 主线程跑完 → 子线程全死
//
//本脚本模拟一个"真实服务"的启动过程,演示正确写法。
//运行后会持续输出心跳日志,按【返回键】或【停止】退出。
//
//怎么用:AIWROK 里直接运行本文件,观察日志输出。
// ============================================================================


// ============================================================================
// 全局变量(坑1:必须在文件最顶部声明)
// ============================================================================
var G = {
    running: true,
    startTime: 0,
    heartbeatCount: 0,
    screen: { w: 1080, h: 1920 }
};


// ============================================================================
// Java 类导入(坑3:必须先 importClass 才能用)
// ============================================================================
importClass(java.net.ServerSocket);
importClass(java.net.InetSocketAddress);
importClass(java.net.NetworkInterface);


// ============================================================================
// 工具函数(坑1:必须先定义,后调用)
// ============================================================================

// 获取屏幕尺寸
function initScreen() {
    try {
      G.screen.w = screen.getScreenWidth();
      G.screen.h = screen.getScreenHeight();
    } catch (e) {
      printl(" 获取屏幕尺寸失败,使用默认值");
    }
    printl("[初始化] 屏幕尺寸: " + G.screen.w + "x" + G.screen.h);
}

// 获取本机 IP
function getLocalIP() {
    try {
      var interfaces = NetworkInterface.getNetworkInterfaces();
      while (interfaces.hasMoreElements()) {
            var iface = interfaces.nextElement();
            if (iface.isLoopback() || !iface.isUp()) continue;
            var addresses = iface.getInetAddresses();
            while (addresses.hasMoreElements()) {
                var addr = addresses.nextElement();
                var host = addr.getHostAddress();
                if (host.indexOf(":") === -1) {// 只取 IPv4
                  return host;
                }
            }
      }
    } catch (e) {}
    return "127.0.0.1";
}

// 格式化运行时长
function formatUptime() {
    var elapsed = Math.floor((java.lang.System.currentTimeMillis() - G.startTime) / 1000);
    var h = Math.floor(elapsed / 3600);
    var m = Math.floor((elapsed % 3600) / 60);
    var s = elapsed % 60;
    return (h < 10 ? "0" : "") + h + ":" +
         (m < 10 ? "0" : "") + m + ":" +
         (s < 10 ? "0" : "") + s;
}


// ============================================================================
// 主流程
// ============================================================================

function main() {
    printl("═══════════════════════════════════════════════════════════");
    printl("AIWROK 避坑案例 #02 - 新手五大坑演示服务");
    printl("═══════════════════════════════════════════════════════════");
    printl("");

    G.startTime = java.lang.System.currentTimeMillis();

    // 阶段1:初始化(模拟真实服务启动流程)
    printl("[阶段1/4] 初始化系统...");
    java.lang.Thread.sleep(500);
    initScreen();
    java.lang.Thread.sleep(300);

    // 阶段2:网络检测
    printl("[阶段2/4] 检测网络环境...");
    java.lang.Thread.sleep(500);
    var ip = getLocalIP();
    printl("[网络] 本机 IP: " + ip);
    java.lang.Thread.sleep(300);

    // 阶段3:模拟端口检测(坑3 的正确用法演示)
    printl("[阶段3/4] 检测端口可用性...");
    java.lang.Thread.sleep(500);
    try {
      var testPort = 32100;
      var testSocket = new ServerSocket(testPort);
      printl("[端口] " + testPort + " 可用 ✓");
      testSocket.close();
    } catch (e) {
      printl("[端口] " + testPort + " 被占用,尝试下一个...");
      testPort++;
    }
    java.lang.Thread.sleep(300);

    // 阶段4:启动完成,进入心跳循环
    printl("[阶段4/4] 启动完成,进入运行状态");
    printl("");
    printl("───────────────────────────────────────────────────────────");
    printl("服务已启动,按【返回键】或【停止】退出");
    printl("───────────────────────────────────────────────────────────");
    printl("");

    // 坑2 的正确用法:用 runTime.setTimeout 做心跳,不用 setInterval
    // 坑5 的正确用法:主线程用递归 setTimeout 保活,不会退出
    startHeartbeat();
}

// 心跳函数(坑2+坑5 的正确写法)
function startHeartbeat() {
    G.heartbeatCount++;

    // 每 3 秒输出一次状态
    var uptime = formatUptime();
    var memInfo = "";
    try {
      var runtime = java.lang.Runtime.getRuntime();
      var usedMB = Math.floor((runtime.totalMemory() - runtime.freeMemory()) / 1048576);
      memInfo = " | 内存: " + usedMB + "MB";
    } catch (e) {}

    printl("[心跳 #" + G.heartbeatCount + "] 运行时长: " + uptime + memInfo);

    // 检查是否该退出(按返回键会设置 G.running = false)
    if (!G.running) {
      printl("");
      printl("═══════════════════════════════════════════════════════════");
      printl("服务已停止,总运行时长: " + formatUptime());
      printl("═══════════════════════════════════════════════════════════");
      return;
    }

    // 递归调用自己(坑2 的正确写法:不用 setInterval)
    runTime.setTimeout(startHeartbeat, 3000);
}

// ============================================================================
// 启动
// ============================================================================
main();

// 说明:按 AIWROK 界面上的【停止】按钮即可退出


页: [1]
查看完整版本: AIWROK函数没定义就调用脚本直接崩