Search code examples
node.jsgulpgulp-watchnode.js-stream

What is the correct way to end a Gulp stream in progress?


I am converting a Grunt build task to a Gulp implementation. I am using gulp-watch, and this is what I've concocted to run my tasks:

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

The problem is, if many files are changed, the task is run too many times. I need to find a way to debounce the input, and cancel any tasks that have been started when new changes come in.

How does one cancel a Node.JS / Gulp stream? I haven't been able to find good documentation on this. I am currently attempting to .end(), but I do not have a guarantee that the Gulp tasks (SASS, Autoprefixer and CleanCSS) will respect this.


Solution

  • It seems like the gulp watch debounce and interval options will handle only specific file, i.e. prevent duplicate calls if the same file was changed. A solution I found to work is to use and external lodash debounce:

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

    or specifically, in your case:

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

    lodash decounce is set by default to trigger on the trailing edge, that means that as long as the events keep coming in, it will wait, and only after there are no events for the the specified period (1000 ms in the example above), the handler will be invoked.

    A few notes:

    1. List item Make sure you npm install and require lodash.
    2. End your return statement in ';' :-)
    3. Choose a proper delay so your handler will go into 'starvation', i.e. never trigger due to on going events or include the maxWait option to make sure it triggers after a reasonable time (say, 3000 ms) regardless of the incoming events.