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.

...

ご覧のとおり、2 つのファイルを変更しましたが、「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 デバウンスを使用した非常に洗練されたソリューションです ;-) (すぐに...)

次の古いコードを使用したときのことを知っておいてください。

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

Grunt は、新しいファイルで coffee タスクを実行するように指示されます。これの問題は、同期プロセスであるため、別のファイルが変更されると (通常、これは数ミリ秒で発生します)、Grunt Watch はdebounceDelayに達するまで別のプロセスを実行できないことです。

デフォルトのdebounceDelayは 500 ミリ秒ですが、watch タスクのオプションを使用して変更できます。(続きを読むoption.debounceDelay について

基本的に、ご覧のように複数のファイルを保存すると、最初に保存されたファイルのみが変更されます。これを回避するために、関数の実行を遅らせる (デバウンスする) ための優れたユーティリティがgrunt.util._.debounceにあります(それへの Lo-Dash リンクはここにあります

関数のパラメーターは次のとおりです。

_.debounce(func, wait, options)

したがって、関数、待機するミリ秒、およびいくつかのオプション (ここでは必要ありません) が必要です。

デバウンスユーティリティを呼び出すと、waitTime だけ関数の実行が遅延されます。一度に複数のファイルを保存すると、すべての呼び出しが 200 ミリ秒後に 1 つの関数呼び出しになります。

その方法 - debounce util以外に、ここで最も便利な行は次のとおりです。

changedFiles[filepath] = action;

(最初は) changedFiles の空のオブジェクトにファイルを追加します。debounce 関数が起動した後、changedFiles obj をリセットして、次の呼び出しに新しく変更されたファイルのみが含まれるようにすることに注意してください。

確かに素晴らしい解決策;-)

于 2013-08-23T09:26:54.057 に答える