【问题标题】:use grunt to restart a phantomjs process使用 grunt 重新启动 phantomjs 进程
【发布时间】:2013-08-27 12:53:09
【问题描述】:

每次我更改代码(例如 jshint)时,我都会使用 grunt 来完成一些任务,并且我想在每次更改时重新加载 phantomJs 进程。

我发现的第一种方法是第一次使用grunt.util.spawn来运行phantomJs。

//  http://gruntjs.com/api/grunt.util#grunt.util.spawn
var phantomJS_child = grunt.util.spawn({
    cmd: './phantomjs-1.9.1-linux-x86_64/bin/phantomjs',
    args: ['./phantomWorker.js']
},
function(){
    console.log('phantomjs done!'); // we never get here...
});

然后,每次 watch 重启时,另一个任务使用 grunt.util.spawn 杀死 phantomJs 进程,这当然非常难看。

有没有更好的方法呢? 问题是 phantomJs 进程没有终止,因为我将它用作网络服务器来为带有 JSON 的 REST API 提供服务。

我是否可以在 watch 启动时进行 grunt 回调或其他操作,以便我可以在重新运行任务以创建新任务之前关闭以前的 phantomJs 进程?

我使用 grunt.event 制作了一个处理程序,但我看不到如何访问 phantomjs 进程以杀死它。

grunt.registerTask('onWatchEvent',function(){

    //  whenever watch starts, do this...
    grunt.event.on('watch',function(event, file, task){
        grunt.log.writeln('\n' + event + ' ' + file + ' | running-> ' + task); 
    });
});

【问题讨论】:

    标签: javascript node.js phantomjs gruntjs grunt-contrib-watch


    【解决方案1】:

    这个完全未经测试的代码可以解决你的问题。

    Node 的原生子生成函数exec 立即返回对子进程的引用,我们可以保留它以便稍后杀死它。要使用它,我们可以动态创建一个自定义的 grunt 任务,如下所示:

    // THIS DOESN'T WORK. phantomjs is undefined every time the watcher re-executes the task
    var exec = require('child_process').exec,
        phantomjs;
    
    grunt.registerTask('spawn-phantomjs', function() {
    
        // if there's already phantomjs instance tell it to quit
        phantomjs && phantomjs.kill();
    
        // (re-)start phantomjs
        phantomjs = exec('./phantomjs-1.9.1-linux-x86_64/bin/phantomjs ./phantomWorker.js',
            function (err, stdout, stderr) {
                grunt.log.write(stdout);
                grunt.log.error(stderr);
                if (err !== null) {
                    grunt.log.error('exec error: ' + err);
                }
        });
    
        // when grunt exits, make sure phantomjs quits too
        process.on('exit', function() {
            grunt.log.writeln('killing child...');
            phantomjs.kill();
        });
    
    });
    

    【讨论】:

    • 我只是在玩 grunt 来熟悉它,然后再使用它。通过这种方式,我们再次手动终止该进程。我不知道我们可以像这样使用“退出”事件。您确定每当手表重新加载任务时,都会触发此“退出”事件吗?当然,在“退出”时杀死它是最好的情况。
    • 抱歉,我将您的用例与我在另一个选项卡上阅读的内容混淆了。刚刚对代码 sn-p 进行了一些编辑,我认为这与您的用例相匹配。但是它不起作用。每次观察者检测到更改时,都会重新执行 Gruntfile.js。因此,不可能对 phantomjs 进行持久引用。反正不是这样的。