在Rhino引擎中实现暂停效果

描述

好吧在文章开始之前, 我想纠正一个名称上的说法, Autojs的用户目前来看分为三大类:

还在使用开源版的用户, 免费 版本号截止到4.1.1之前

使用Pro8.0版本的用户, 该版本不包含node引擎,只有Rhino引擎

使用Pro9.0版本的用户, 该版本包含Node和Rhino两个引擎

免费版我们就称为免费版, Pro8.0版本,直接说8.0版本或者pro8,同理9.0一样9.0版本或者pro9, 现在对于8.0和9.0的autojs存在很多叫法, 这种叫法非常容易和别的概念混淆,什么V8. V9 V8引擎, 一代引擎, 二代引擎,各种奇葩叫法, 请放弃这些花里胡哨的说法, 直接回归最基本的名称好吧,方便大家沟通, 另外一代 二代的叫法只是对于文档来说的.

8.0版本中只有rhino引擎,它使用的是JavaScript ES5标准,另外有少许的ES6特性,使用时,阅读官网的一代文档, 8.0不包含NodeJS引擎,也就是说,Nodejs的代码无法在8.0版本中运行;

9.0版本中包含8.0版本的Rhino引擎,使用方法和8.0一样,开发文档使用一代文档(注意不要称为一代引擎), 另外从9.0版本开始加入了Node引擎,可以使用nodejs来开发项目,node引擎使用的是二代文档, Node引擎和Rhino引擎都可以在pro9.x版本以上使用.

因此,如果你使用的是Pro9.x版本,遇到问题, 请像这样描述: "我使用的是Pro9, 代码开发使用的是rhino引擎, 在运行时遇到下列错误...", "我使用的是9.0版本,使用的是Node引擎开发环境, 运行代码时发生这样的错误..."


正文开始: (不好意思忍不住吐槽了一下.)

昨天,又遇到来问,JS代码中怎么暂停/继续代码的执行,之前一直不想做这个功能, 因为JS本身在运行时,就不支持暂停,如果非要做暂停的话. 我能给出的方案,只有使用死循环来暂停运行, 其大概原理, 循环判断某个属性的值是否符合预期,如果符合,就暂停运行, 不符合了就跳出循环,继续执行下方的代码, 并且呢,这个死循环,要加到代码的每一行中.

呵~这种做法,TMD听起来就有点离谱.既然非得要,那必然得牺牲点什么罢...

那么,干货来了, 下面的代码是封装好的一个模块:

module.exports = ( function() {


    let MianThread;


    let IsRun = false;
    let IsPause = false;
    //就是在要运行的代码中逐行插入这句代码...
    let PauseFun = "while( true ){ if ( !IsPause ) { break; } sleep( 10 ); }";

    this.SetRunState = function( state ) {
        IsRun = state;
    }
    this.GetRunState = function() {
        return IsRun;
    }
    this.SetPauseState = function( state ) {
        IsPause = state;
    }
    this.GetPauseState = function () {
        return IsPause;
    }
    /**
     * 保证功能不会被重复运行.
     * @param {*} main 要执行的功能函数
     * @returns void
     */
    this.RunScript = ( main ) => {
        try {
            if ( this.GetRunState() ) {
                toastLog( "该功能正在运行,无法重复运行" );
                return;
            }
            let mainStr = main.toString();
            let mainStrArry = mainStr.split( "\\n" );
            let mainFunStr = "";
            for ( let i in mainStrArry ) {
                if ( mainStrArry[ i ] == "" ) continue;
                if ( i <= mainStrArry.length - 3 ) {
                    mainFunStr += mainStrArry[ i ] + "\\n" + PauseFun + "\\n";
                }
            }
            mainFunStr += "}";
            main = eval( mainFunStr );
            // log(main.toString());
            this.SetRunState( true );
            MianThread = threads.start( main );
        } catch ( e ) {
            toastLog( "[ CATCH_INFO ]: " + e );
            this.SetRunState( false );
            return;
        }
        //等待运行脚本的线程执行完成,改变状态
        threads.start( () => {
            if ( MianThread ) {
                MianThread.join();
                this.SetRunState( false );
            }
        } );
    }
    this.Stop = function() {
        if ( this.GetRunState() ) {
            MianThread.interrupt();
        }
    }

    this.Pause = function() {
        if ( !this.GetPauseState() ) {
            this.SetPauseState( true );
            console.log("当前逻辑已暂停!");
        } else {
            console.log( "继续执行代码逻辑" );
            this.SetPauseState( false );
        }
    }


    return this;
} )()

模块中封装了几个方法, 通过两个属性的bool值去控制 传入方法的运行状态. 在使用runScript( main ); 方法时, 对于传入的main函数,进行重新封装,逐行插入死循环代码...然后再运行这个函数. 在线程外通过Pause()方法去控制暂停和继续.然后写一个简单的demo.

"ui";


$ui.layout( 
    "*" gravity="center|center_horizontal|center_vertical">
        "center|center_horizontal|center_vertical" margin="20" cardCornerRadius="8dp" cardElevation="5dp" >
            "20 10" gravity="center|center_horizontal|center_vertical">
                
                    "16sp">运行结果: class="hljs-name"text>
                    "runResult" inputType="text" singleLine="true" gravity="center"  w="*" h="60" textSize="18sp" />
                class="hljs-name"linear>
                "center" >
                    
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分