Node.js 在咕噜声中,如果我';我正在查看多个文件和两个或多个更改,如何仅对更改的文件运行任务?

Node.js 在咕噜声中,如果我';我正在查看多个文件和两个或多个更改,如何仅对更改的文件运行任务?,node.js,gruntjs,grunt-contrib-watch,Node.js,Gruntjs,Grunt Contrib Watch,我有一个initConfig,其中包含以下代码: grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), watch: { options: { spawn: false }, coffee: { files: [ 'src/**/*.coffee' ],

我有一个
initConfig
,其中包含以下代码:

grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    watch: {
        options: {
            spawn: false
        },
        coffee: {
            files: [
                'src/**/*.coffee'
            ],
            tasks: ['coffee', 'coffeelint', 'concat', 'qunit']
        },

...
    coffee: {
        glob_to_multiple: {
            expand: true,
            flatten: false,
            cwd: '.',
            src: ['src/**/*.coffee'],
            ext: '.js'
        }
    },

...

grunt.event.on('watch', function (action, filepath) {
    if (grunt.file.isMatch("**/*.coffee", filepath)) {
        grunt.config(['coffee', 'glob_to_multiple', 'src'], filepath);
    }
});
这应该只编译已更改的.coffee文件。这很有效。但我注意到,如果我一次修改多个,它将输出以下内容:

Waiting...src\test\resources\app\js\FILE1.coffee
src\main\resources\app\js\FILE2.coffee
OK
>> File "src\test\resources\app\js\FILE1.coffee" changed.
>> File "src\main\resources\app\js\FILE2.coffee" changed.


Running "coffee:glob_to_multiple" (coffee) task
File src/main/resources/app/js/FILE2.js created.

...
如您所见,我已经更改了两个文件,但它只运行“FILE2.js”上的任务。我怎样才能避免这种情况?我希望它在FILE1和FILE2上运行
coffee:glob\u to\u multiple
,而不仅仅是其中一个


注:我很确定解释了如何做到这一点:

如果同时保存多个文件,则可以选择更可靠的方法:

根据该文档,我对代码进行了以下更改:

var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
    grunt.config(['coffee', 'glob_to_multiple', 'src'], Object.keys(changedFiles));
    changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
    if (grunt.file.isMatch("**/*.coffee", filepath)) {
        changedFiles[filepath] = action;
        onChange();
    }
});

事情完全按照我想要的方式进行但我不确定这是怎么回事。有人能给我解释一下吗?

这是一个非常复杂的解决方案,使用Lo Dash debounce;-)(一秒钟内…)

要知道,当您使用旧代码时:

 grunt.config(['coffee', 'glob_to_multiple', 'src'], filepath);
Grunt被指示使用新文件运行coffee任务。问题是这是一个同步进程,因此当另一个文件发生更改时(通常在几毫秒内发生),Grunt Watch将不允许您运行另一个进程,直到达到去BounceDelay

默认的去BounceDelay为500毫秒,但这可以使用“监视”任务的选项进行更改。(阅读更多

基本上,当您保存多个文件时,正如您所看到的,只有保存的第一个文件会被更改。为了避免这种情况,延迟(去Bouncing)函数运行的一个很好的实用工具是grunt.util.\uu.debounce(指向它的短划线链接是

该函数的参数为:

_.debounce(func, wait, options)
所以它需要函数、等待的毫秒数和一些选项(我们这里不需要)

当您调用debounce实用程序时,它将延迟函数的执行等待时间,这样,当您一次保存多个文件时,所有调用将在这200毫秒的时间段后加起来成为一个函数调用

这样-除了去盎司util之外,这里最有用的一行是:

changedFiles[filepath] = action;
这会将文件添加到(最初)changedFiles的空对象中。请注意,在debounce函数启动后,我们会重置changedFiles对象,以便下一次调用只包含新更改的文件


令人惊讶的解决方案;-)

可能与@SindreSorhus重复不,不是。区别在于,这是关于在多个文件发生更改时运行任务。很酷,谢谢你的回答。我不知道这是一个lodash调用,它阻止了我学习。我认为watch api的配置应该开箱即用。它应该有一个
选项:{runTaskOnOnlyChangedFiles:true}
。实际上grunt contrib watch还有很多工作要做……你可以贡献这一点,并建议他们将其添加到下一个版本中。我想已经有人要求了:
changedFiles[filepath] = action;