前言
大家好,我是鲫小鱼。是一名不写前端代码
的前端工程师,热衷于分享非前端的知识,带领切图仔逃离切图圈子,欢迎关注我,微信公众号:《鲫小鱼不正经》
。欢迎点赞、收藏、关注,一键三连!!
第七章:定时任务调度
一、理论讲解:定时任务的意义与原理
在自动化脚本开发中,定时任务调度是实现"无人值守"自动化的核心能力。无论是定时签到、定时备份、定时推送消息,还是周期性监控、批量处理,都离不开高效、可靠的定时调度机制。
1.1 定时任务的常见场景
- 每天定时自动签到/打卡/抢红包
- 定时备份数据、同步文件、上传日志
- 定时推送消息、提醒、通知
- 周期性监控App状态、自动重启
- 多账号/多任务批量定时执行
1.2 Auto.js 定时机制原理
- 通过 timers.setInterval/setTimeout 实现周期性/延时任务
- 结合 threads 多线程,实现主流程与定时任务并发
- 可与 Android AlarmManager、系统定时器结合实现更强大功能
- 支持自定义调度策略、任务优先级、动态调整
二、基础用法与代码示例
2.1 基本定时任务
javascript
// 每隔10秒执行一次任务
timers.setInterval(function(){
toast("定时任务执行中");
}, 10000);
2.2 延时任务
javascript
// 延时5秒后执行一次
timers.setTimeout(function(){
toast("延时任务已执行");
}, 5000);
2.3 多定时器并发
javascript
// 启动多个定时任务
timers.setInterval(function(){
toast("任务A");
}, 5000);
timers.setInterval(function(){
toast("任务B");
}, 8000);
2.4 动态调整定时周期
javascript
// 动态调整定时器周期
var interval = 10000;
var timerId = timers.setInterval(function(){
toast("动态周期任务");
}, interval);
// 5秒后调整周期
setTimeout(function(){
timers.clearInterval(timerId);
interval = 3000;
timerId = timers.setInterval(function(){
toast("新周期任务");
}, interval);
}, 5000);
2.5 定时任务与多线程结合
javascript
// 子线程定时执行任务
threads.start(function(){
timers.setInterval(function(){
toast("子线程定时任务");
}, 7000);
});
2.6 定时任务与UI交互
javascript
// 定时更新UI内容
"ui";
ui.layout(
<vertical>
<text id="clock" textSize="30sp" textColor="#333" />
</vertical>
);
timers.setInterval(function(){
ui.run(function(){
ui.clock.setText(new Date().toLocaleTimeString());
});
}, 1000);
2.7 定时任务的取消与重启
javascript
// 启动和取消定时任务
var timerId = timers.setInterval(function(){
toast("循环任务");
}, 2000);
// 10秒后取消
timers.setTimeout(function(){
timers.clearInterval(timerId);
toast("定时任务已取消");
}, 10000);
2.8 定时任务与数据存储
javascript
// 定时保存数据到本地
var count = 0;
timers.setInterval(function(){
files.write("/sdcard/autojs_count.txt", "计数:" + (++count));
}, 3000);
2.9 定时任务与网络请求
javascript
// 定时请求接口并处理数据
timers.setInterval(function(){
http.get("https://api.github.com", {}, function(res, err){
if(err){
toast("请求失败");
return;
}
toast("状态码:" + res.statusCode);
});
}, 15000);
2.10 定时任务与异常处理
javascript
// 定时任务加异常捕获,防止崩溃
timers.setInterval(function(){
try{
// 可能抛错的操作
toast("安全定时任务");
}catch(e){
log("定时任务异常:" + e);
}
}, 5000);
三、实战项目:定时自动打卡脚本
3.1 需求分析
- 每天早上8点自动打开App并打卡
- 支持手动一键打卡与定时自动打卡
- 支持打卡结果日志、异常处理、历史记录
- 支持UI界面配置打卡时间、App包名、打卡按钮文本
3.2 项目结构
plaintext
autojs-clockin/
├── main.js
├── modules/
│ ├── clockin.js
│ └── logger.js
├── data/
│ └── history.json
├── ui/
│ └── config_ui.js
├── logs/
│ └── clockin.log
└── README.md
3.3 UI界面 config_ui.js
javascript
"ui";
ui.layout(
<vertical padding="16">
<text textSize="22sp" textColor="#222">定时打卡配置</text>
<input id="time" hint="打卡时间(如08:00)" />
<input id="package" hint="App包名" />
<input id="btnText" hint="打卡按钮文本" />
<button id="btnStart" text="立即打卡" />
<button id="btnHistory" text="查看历史" />
<text id="result" textColor="#666" />
</vertical>
);
ui.btnStart.on("click", () => {
threads.start(function(){
let res = require("../modules/clockin.js").run({
package: ui.package.text(),
btnText: ui.btnText.text()
});
ui.result.setText(res ? "打卡成功" : "打卡失败");
});
});
ui.btnHistory.on("click", () => {
let history = files.read("../data/history.json");
dialogs.alert("打卡历史", history || "暂无记录");
});
3.4 主入口 main.js
javascript
// main.js
const config = require("./ui/config_ui.js");
const clockin = require("./modules/clockin.js");
const logger = require("./modules/logger.js");
// 定时调度函数
timers.setInterval(function(){
let now = new Date();
let target = ui.time.text().split(":");
if(now.getHours() == parseInt(target[0]) && now.getMinutes() == parseInt(target[1])){
logger.log("定时自动打卡开始");
clockin.run({
package: ui.package.text(),
btnText: ui.btnText.text()
});
}
}, 60000); // 每分钟检查一次
3.5 核心打卡逻辑 modules/clockin.js
javascript
// modules/clockin.js
const logger = require("./logger.js");
function run(opt) {
logger.log(`启动App:${opt.package}`);
app.launch(opt.package);
sleep(5000);
if (text(opt.btnText).exists()) {
text(opt.btnText).findOne().click();
sleep(2000);
logger.log("打卡成功");
saveHistory(true);
return true;
}
logger.log("打卡失败");
saveHistory(false);
return false;
}
function saveHistory(success) {
let history = files.exists("../data/history.json") ? JSON.parse(files.read("../data/history.json")) : [];
history.push({ success, time: new Date().toLocaleString() });
files.write("../data/history.json", JSON.stringify(history, null, 2));
}
module.exports = { run };
3.6 日志模块 modules/logger.js
javascript
// modules/logger.js
function log(msg) {
let line = `[${new Date().toLocaleTimeString()}] ${msg}`;
files.append("../logs/clockin.log", line + "\n");
toast(msg);
}
module.exports = { log };
四、分步详解与进阶技巧
4.1 多任务定时调度
- 支持多个定时任务并发执行
- 支持任务优先级、动态添加/删除/调整
4.2 定时任务与多线程结合
- 主线程调度,子线程执行任务,互不阻塞
- 支持任务超时、失败重试、异常捕获
4.3 定时任务与UI联动
- 定时更新UI内容、进度条、状态提示
- 支持定时推送消息、弹窗提醒
4.4 定时任务与数据存储
- 定时备份、同步、上传数据
- 定时清理缓存、日志、历史记录
4.5 定时任务与网络请求
- 定时同步远程数据、自动签到、自动打卡
- 支持失败重试、超时处理、结果推送
4.6 定时任务的取消与重启
- 支持一键暂停/恢复/重启定时任务
- 支持任务状态监控、日志记录
4.7 定时任务的异常与容错
- try-catch 捕获异常,日志记录
- 任务失败自动重试、报警
4.8 定时任务的性能优化
- 合理设置周期,避免过于频繁
- 任务分批执行,避免资源争抢
- 日志分级输出,避免刷屏
- 任务队列+线程池提升并发效率
五、常见问题与解决方案
问题 | 解决方案 |
---|---|
定时任务不准/丢失 | 检查 timers、线程、App 后台限制 |
多定时器冲突/卡顿 | 合理分配周期、优化任务粒度、使用线程池 |
定时任务崩溃/异常未捕获 | try-catch 捕获异常,日志记录,自动重启 |
定时任务无法取消/重启 | 保存 timerId,及时 clearInterval/clearTimeout |
定时任务与UI不同步 | 用 ui.run() 或 events 传递到主线程 |
定时任务执行慢/卡主线程 | 用子线程、异步处理耗时操作 |
定时任务日志无输出 | 检查日志路径、权限、输出逻辑 |
定时任务与数据存储冲突 | 加锁、队列、分片处理,避免并发写入 |
六、性能优化建议
- 合理设置定时周期,避免过于频繁
- 主线程只做调度,耗时任务用子线程/异步
- 定时任务加超时与重试,防止卡死
- 日志分级输出,开发阶段多输出,正式运行时降级
- 任务队列+线程池提升并发效率
- 定时任务异常自动重启,提升健壮性
- 合理 sleep,避免无效等待
- 任务状态监控,及时释放资源
- 任务分批执行,避免资源争抢
最后感谢阅读!欢迎关注我,微信公众号:
《鲫小鱼不正经》
。欢迎点赞、收藏、关注,一键三连!!!