Autox.js 中文文档 下载 App

Autox.js 等待超时与 until 避免 findOne 死等和 sleep 盲等

脚本里最容易写错的就是等待

写脚本时最常见的两个错误:

// 错误一:死等——如果控件永远不出现,脚本卡死
text("欢迎").findOne();

// 错误二:盲等——sleep 时间要么不够(脚本报错),要么浪费
sleep(3000);
text("欢迎").findOne().click();

Autox.js 提供了主动等待机制,帮你避免这两个坑。

findOne 带超时

// 正确写法:最多等 5 秒
let btn = text("确定").findOne(5000);
if (btn) {
    btn.click();
} else {
    toast("5 秒内没找到确定按钮");
}

findOne(timeout) 在 timeout 毫秒内持续轮询控件树(通常每秒几次),一旦找到就立即返回,超时返回 null。这比固定 sleep 高效得多——控件 1 秒就出来了,你不用傻等 3 秒。

until:等待控件出现

until() 的语义是"等到这个选择器匹配到控件为止":

// 等到"登录成功"提示出现(最多 10 秒)
let success = text("登录成功").until(10000);
if (success) {
    toast("登录成功");
} else {
    toast("10 秒内没等到成功提示");
}

和 findOne(timeout) 非常相似,返回值也一样——找到返回控件、超时返回 null。区别在于语义上的意图:

API语义适用场景
findOne(timeout)查找一个控件我知道它应该在那里,找到它来操作
until(timeout)等待某个状态变化等异步操作(登录请求、加载动画)完成

全局 exists 检查

如果你只是想知道"屏幕上有没有这个控件",不需要等它:

if (text("退出").exists()) {
    toast("找到了退出按钮");
} else {
    toast("当前页面没有退出按钮");
}

exists() 是瞬间检查,不轮询、不等待。需要等还是用 findOne(timeout) 或 until(timeout)。

处理弹窗和异常页面

脚本跑着跑着可能突然冒出个弹窗(权限请求、广告、更新提示)。主动等待机制能让你提前处理这些情况:

// 在正常等待目标页的同时,监听弹窗
Promise.race([
    // 正常路径
    text("首页").until(10000),
    // 异常路径:权限弹窗
    text("允许").until(3000),
    text("拒绝").until(3000),
]).then(result => {
    if (result === "允许") {
        text("允许").findOne().click();
    } else if (result === "拒绝") {
        text("拒绝").findOne().click();
    } else {
        toast("正常进入首页");
    }
});

sleep 什么时候还能用

sleep() 不应该用来等控件出现,但有几个场景还是需要它:

场景为什么需要 sleep
启动 App 后launchApp() 不阻塞,App 冷启动需要时间初始化
网络请求服务器响应时间不可预测,通常用 until() 等结果页
动画过渡某些界面切换有过渡动画,需要等动画结束再操作
节流操作某些高频操作(快速点击、快速 scroll)如果不 sleep 可能被系统限流
// 典型正确用法
launchApp("com.example.app");
sleep(2000);  // 等 App 启动

// 然后用 until 等具体页面
if (!text("首页").until(10000)) {
    exit("首页没加载出来");
}

实战:健壮的页面切换

function goToSettings() {
    // 点击我的 Tab
    let mineTab = text("我的").findOne(10000);
    if (!mineTab) {
        toast("没找到我的 Tab");
        return false;
    }
    
    mineTab.click();
    
    // 等待"设置"按钮出现
    let settings = text("设置").until(10000);
    if (!settings) {
        toast("点击我的 Tab 后没等到设置按钮");
        return false;
    }
    
    settings.click();
    
    // 等待设置页加载
    if (!text("通用").until(5000)) {
        toast("设置页加载失败");
        return false;
    }
    
    return true;
}

goToSettings();

总结对比

API是否轮询超时参数返回值适合
textExists()❌ 瞬间无boolean瞬间检查
findOne()✅ 无限等可选控件或 null不推荐无超时
findOne(timeout)✅ 限轮询毫秒数控件或 null查找 + 自动等待
until(timeout)✅ 限轮询毫秒数控件或 null等待状态变化
sleep(ms)❌ 盲等毫秒数void节流/动画/启动等待