1

我有一个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”上运行任务。我怎样才能避免这种情况?我希望它coffee:glob_to_multiple在 FILE1 和 FILE2 上运行,而不仅仅是其中一个。


注意:我很确定文档解释了如何执行此操作:

如果您同时保存多个文件,您可能会选择更强大的方法:

var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
  grunt.config(['jshint', 'all'], Object.keys(changedFiles));
  changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
  changedFiles[filepath] = action;
  onChange();
});

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

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();
    }
});

事情完全按照我想要的方式进行。 但我不确定这是如何工作的。有人可以向我解释吗?

4

1 回答 1

2

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

知道当您使用旧代码时:

 grunt.config(['coffee', 'glob_to_multiple', 'src'], filepath);

Grunt 被指示使用新文件运行咖啡任务。这样做的问题是它是一个同步过程,因此当另一个文件被更改时(通常这会在几毫秒内发生),然后 Grunt Watch 将不允许您运行另一个进程,直到达到debounceDelay

默认debounceDelay为 500 毫秒,但可以使用监视任务的选项进行更改。(阅读更多关于 option.debounceDelay

基本上,当您保存多个文件时,如您所见 - 只有第一个保存的文件被更改。为了绕过这个,延迟(去抖动)函数运行的一个很好的实用程序是在grunt.util._.debounce(Lo-Dash 链接在这里

该函数的参数是:

_.debounce(func, wait, options)

所以它需要函数,等待多少毫秒,以及一些选项(我们在这里不需要)。

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

这样 - 除了debounce util 之外,这里最有用的行如下:

changedFiles[filepath] = action;

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

确实是惊人的解决方案;-)

于 2013-08-23T09:26:54.057 回答