js 如何优化这种情形: 无限状态切换 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
ethusdt
0.01D
V2EX    Javascript

js 如何优化这种情形: 无限状态切换

  •  
  •   ethusdt 2021-12-19 18:14:14 +08:00 2750 次点击
    这是一个创建于 1467 天前的主题,其中的信息可能已经有所发展或是发生改变。
    function start() { var screen = captureScreen(); // 出现弹框, 干掉弹框 if (screen.find(ALERT_BUTTON) { click(ALERT_CLOSE_BUTTON); start(); } // 如果有返回按钮, 点击返回 if (screen.find(BACK_BUTTON) { click(BACK_BUTTON); start(); } // 如果不在首页(首页没有高亮选中), 点击回到首页 if (screen.find(HOME_BUTTON_UNHIGHLIGHT) { click(HOME_BUTTON_UNHIGHLIGHT); start(); } // 在首页了, 有“喜欢按钮” if (screen.find(LIKE_BUTTON) { click(LIKE_BUTTON); swipeNextVideo(); sleep(5000); start(); } } setInterval(function() { if (currentPackage() !== 'PACKAGE_NAME') { launch('PACKAGE_NAME'); } }, 1000*60*10) // 10 分钟检查一次程序是否被杀死, 程序不在运行就重新打开 start(); 

    以上是脚本程序的大概逻辑:

    打开某视频软件, 如果有弹框, 干掉弹框, 如果不在首页, 返回首页, 刷视频点赞, 然后继续下一轮

    程序使用了递归, 如果运行时间过长, 内存占用会变大. 有什么方法可以优化这一点?

    我尝试过使用 whilecontinue:

    while (true) { if (condition1) { doSometing2(); continue; } if (condition2) { doSometing2(); continue; } .. } 

    死循环会让外面的 setInterval 不被执行.

    还尝试过使用 generator 来做, 配合 redux-saga, 但这个框架不支持 es6, 在使用 babel 转译时候, 遇到一堆问题, 就跑不通了.

    所以除了 以上几种方法, 还有什么方法可以优化吗?

    15 条回复    2021-12-20 14:00:28 +08:00
    MegrezZhu
        1
    MegrezZhu  
       2021-12-19 18:28:42 +08:00
    我想了很多,写了一点伪代码,然后删掉了。
    为什么不直接五分钟重启一次脚本呢[狗头]
    ch2
        2
    ch2  
       2021-12-19 18:29:50 +08:00
    看了一下,你应该使用定时任务而不是递归来完成你想要的操作
    加一个全局变量 working ,start 开始的时候设置 working 为 true ,结束的时候设置为 false
    然后定时每隔 10 秒触发一次 start ,如果正在 working 直接 return
    再把 start 函数里把递归调用自己的全部注释掉
    lscho
        3
    lscho  
       2021-12-19 18:34:09 +08:00
    递归引起的堆栈溢出改成尾递归或者匿名函数都可以解决。但是你的代码里最明显的是 setInterval 问题,setInterval 长时间运行会内存增大不是常识吗?先把这个解决了再看是不是递归的问题吧。
    ethusdt
        4
    ethusdt  
    OP
       2021-12-19 18:54:13 +08:00
    @MegrezZhu 额, 上面只是个 demo, 实际代码比这复杂的多, 要抢红包 /抢东西, 需要每 300 毫秒截图判断, 重启脚本这代价太大了.


    @ch2 哦. 知道了, 我太愚蠢了. 可以直接 setInterval(start, 500) 来做无限循环. 本来没想用这方法是考虑到有这情形:

    function start() {
    ...
    if(cond) callA();
    ...
    }

    function callA() {
    var someVars = ...;
    doMainTask();
    setTimeout(function() {
    // 10 秒钟没干完,直接退出
    closureUseVar(someVars);
    cancelMainTask();
    exitPage();
    start(); // here 又递归了
    }, 10000)
    }

    (v2ex 回复会把代码缩进吃掉)

    这样, 按你的方法, 加一个 flag 控制, 使用 setInterval 来进行无限循环就可以了. 在使用到递归的地方 直接设置 `flag = !flag`;
    ethusdt
        5
    ethusdt  
    OP
       2021-12-19 19:02:03 +08:00
    @lscho setInterval 长时间运行为啥会增大内存? 我没考虑到这个问题. interval 结束函数都被 GC 了吧 ?
    ethusdt
        6
    ethusdt  
    OP
       2021-12-19 19:09:17 +08:00
    @lscho 确实搜到 setInterval 在浏览器下, 如果浏览器 tab 不是激活状态, 会有积压的问题, 导致一下子执行很多函数, 浏览器卡死. t/761311
    ethusdt
        7
    ethusdt  
    OP
       2021-12-19 19:11:17 +08:00
    @lscho 那用 setTimeout 来代替:
    setTimeout(function repeat() {
    func();
    setTimeout(repeat, 9000);
    }, 9000);
    rpman
        8
    rpman  
       2021-12-19 22:53:09 +08:00
    Looping 的话应该 sleep 一下吧
    或者可以写成 Event driven
    ethusdt
        9
    ethusdt  
    OP
       2021-12-19 23:11:01 +08:00
    @rpman 嗯. 是的 就是 sleep 的, 要不然 cpu 受不了.
    2i2Re2PLMaDnghL
        10
    2i2Re2PLMaDnghL  
       2021-12-20 09:47:37 +08:00
    @lscho 尾调用优化目前只有 safari 或者用 babel 支持吧
    lscho
        11
    lscho  
       2021-12-20 10:44:51 +08:00
    @2i2Re2PLMaDnghL babel 只是把浏览器不支持的语法转为支持的,既然他能转,那就能写出来啊
    2i2Re2PLMaDnghL
        12
    2i2Re2PLMaDnghL  
       2021-12-20 11:17:17 +08:00
    @lscho 哦你是说手写 TCO 啊
    其实 OP 主题里的 start 把后续 if 全转 else if 并把 start() 换成 return start() 的话,所有 start() 就都在尾位置上了,我以为你是指这个……
    iPhone12
        13
    iPhone12  
       2021-12-20 12:40:38 +08:00 via iPhone
    1 中可以将 sleep 去掉,最后再 setTimeout(start, 0 或者 500),不会爆栈也不会阻塞后面的 setInterval
    Fatpandac
        14
    Fatpandac  
       2021-12-20 13:53:10 +08:00
    ```
    // 在首页了, 有“喜欢按钮”
    if (screen.find(LIKE_BUTTON) {
    ```
    发现 bug ,少了个右括号:joy:
    ethusdt
        15
    ethusdt  
    OP
       2021-12-20 14:00:28 +08:00
    @Fatpandac 哦.. 我都是手打的 没太注意括号, 习惯了编辑器自动补全.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2780 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 14:39 PVG 22:39 LAX 06:39 JFK 09:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86