Как правильно завершить текущий поток Gulp?

Я конвертирую задачу сборки Grunt в реализацию Gulp. Я использую gulp-watch, и это то, что я придумал для выполнения своих задач:

gulp.task('task', function(){
    return watch('glob/**/*', function(){
        var stream = doTask();
        return stream;
    })
});

Проблема в том, что если изменено много файлов, задача запускается слишком много раз. Мне нужно найти способ отменить ввод и отменить все задачи, которые были запущены, когда поступают новые изменения.

Как отменить поток Node.JS/Gulp? Я не смог найти хорошую документацию по этому вопросу. В настоящее время я пытаюсь .end(), но у меня нет гарантии, что задачи Gulp (SASS, Autoprefixer и CleanCSS) будут соблюдать это.


person Bryan Rayner    schedule 16.10.2015    source источник


Ответы (2)


Похоже, что параметры gulp watch debounce и interval будут обрабатывать только конкретный файл, т. е. предотвращать повторяющиеся вызовы, если один и тот же файл был изменен. Решение, которое я нашел работающим, заключается в использовании внешнего lodash:

watch(GLOB_expression, _.decounce(handler, delay));

или конкретно в вашем случае:

gulp.task('task', function(){
    return watch('glob/**/*', _.debounce(function(){
        var stream = doTask();
        return stream;
    }, 1000));
});    

lodash decounce по умолчанию настроен на срабатывание по заднему фронту, это означает, что пока события продолжают поступать, он будет ждать, и только после того, как нет событий в течение указанного периода (1000 мс в приведенном выше примере), обработчик будет вызван.

Несколько заметок:

  1. Элемент списка Убедитесь, что вы установили npm и требуете lodash.
  2. Завершите оператор return символом ';' :-)
  3. Выберите правильную задержку, чтобы ваш обработчик перешел в состояние «голодания», т. е. никогда не срабатывал из-за происходящих событий, или включите параметр maxWait, чтобы убедиться, что он срабатывает через разумное время (скажем, 3000 мс) независимо от того, поступающих событий.
person Meir    schedule 16.10.2015
comment
Я знаком с debounce и рассматривал его. Я не был уверен, что это сработает на gulp-watch, так как обычно он ищет поток, который будет возвращен функцией, и я не уверен, как он будет обрабатывать ложное значение. Я попробую, спасибо. - person Bryan Rayner; 16.10.2015
comment
Ваш обработчик не принимает никаких параметров, просто запускает функцию. Отказ от дребезга задержит запуск этого действия. Он должен работать. Я буду рад, если вы добавите комментарий после того, как попробовали его, и сообщите нам, правильно ли он работает. - person Meir; 16.10.2015
comment
Глядя на это, откат на основе времени не решит мою проблему (если только я не смогу отменить уже запущенный поток). Выполнение задачи занимает около 10 секунд, а это означает, что изменения файла могут запускать новые задачи более один раз, пока он уже работает. Я действительно не хочу запускать более одной из этих задач одновременно. Я либо могу остановить уже запущенный поток (тогда я могу использовать откат на основе времени), либо мне нужен откат, который предотвращает запуск событий до тех пор, пока задача не будет завершена. - person Bryan Rayner; 16.10.2015
comment
Задание запустится только в том случае, если в течение xxx времени не было событий. Если он уже запущен, дайте ему закончиться, и следующий вызов обновит ваши данные. Отмена задачи (почти) эквивалентна запуску задачи только тогда, когда все ваши события молчат в течение достаточного времени. В качестве альтернативы вы можете удерживать дескриптор последнего возвращенного вами потока, и когда вы запускаете новый поток, сначала завершить предыдущий, выпустив для него «конец» или любой другой метод завершения потока (вы не указали свой тип потока, поэтому я нельзя конкретно) - person Meir; 16.10.2015
comment
Я не уверен в типе потока. Я вполне уверен, что будет выдана ошибка «запись после завершения», если задача попытается записать после вызова end(). Итак, если у меня есть куча операций, которые я прикрепил через pipe(), они прекратятся после того, как я вызову end? Может быть, я слишком много думаю. - person Bryan Rayner; 16.10.2015

В итоге я сделал небольшой класс для буферизации потоков.

https://gist.github.com/bryanerayner/cc2bb9b4da243d94f0f8

Глотковый файл:

function setupQuickSassJob(sourceGlob, watchGlob) {
    function job() {

        function taskFactory() {
            return jobs.processSassStyles(
                    gulp.src([].concat(sourceGlob), { base: '.' }),
                    '.');
        }

        gUtil.log('Listening for changes');

        var queue = new StreamQueue();

        var watchtask = watch([].concat(watchGlob), function (file) {

            gUtil.log('Changed: ' + file.path);

            return queue.queueTask(taskFactory);
        });

        return watchtask;
    }
    return job;
}

gulp.task('desktopSASS', setupQuickSassJob([
    'Globs',
],
[
    'Globs'
    ]
));

Я не совсем доволен этим, но это работает. Если у кого-то есть более правильный способ Node сделать это, я весь слушаю.

person Bryan Rayner    schedule 16.10.2015