javascript Gulp.js,保存文件时watch任务运行两次

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21608480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 21:18:13  来源:igfitidea点击:

Gulp.js, watch task runs twice when saving files

javascriptgulp

提问by ?yvind

Given the following piece of code from my gulpfile.js, everytime I save or change a file, the task runs twice instead of one single time, why is that? I just want it to run one time.

鉴于我的 gulpfile.js 中的以下一段代码,每次我保存或更改文件时,任务都会运行两次而不是一次,这是为什么?我只希望它运行一次。

var gulp = require('gulp');

gulp.task('default', function() {

  gulp.watch('server/**/*.js', function(){
    console.log('This runs twice everytime I change/save a javascript file located at server/**/*.js');
  }); 

});

I have also experienced the same with grunt and the plugin called grunt-contrib-watch.

我对 grunt 和名为 grunt-contrib-watch 的插件也有同样的体验。

采纳答案by ?yvind

Seems like the answer to this question is a feature of the editor that was used, Coda 2. Based on some of the comments here and testing with multiple editors, it seems like Coda 2 saves a temporary file or similar and that causes the gulp watch function to be run twice.

似乎这个问题的答案是使用的编辑器 Coda 2 的一个功能。根据这里的一些评论和多个编辑器的测试,似乎 Coda 2 保存了一个临时文件或类似文件,这会导致 gulp watch函数运行两次。

I have not found a viable solution to this when using Coda 2, ended up with switching to Sublime Text 3.

在使用 Coda 2 时,我还没有找到可行的解决方案,最终切换到 Sublime Text 3。

回答by Ryan Atallah

The problem is occurring because your editor, in this case Coda 2, is modifying the file twice on save. The same problem occurs in vim because of how vim creates buffer backups on save.

出现问题是因为您的编辑器(在本例中为 Coda 2)在保存时修改了文件两次。由于 vim在 save 时创建缓冲区备份的方式,vim 中也会出现同样的问题。

The solution to the problem in vim is to add

vim中问题的解决方法是添加

set nowritebackup

to your ~/.vimrcfile. This changes the default save protocol to only make one edit to the original file.

到您的~/.vimrc文件。这会将默认保存协议更改为仅对原始文件进行一次编辑。

In other words, the default save protocol is as follows:

也就是说,默认的保存协议如下:

  1. Write the buffer to the backup file
  2. Delete the original file
  3. Rename the backup to the name of the original file
  1. 将缓冲区写入备份文件
  2. 删除原始文件
  3. 将备份重命名为原始文件的名称

And adding set nowritebackupsimply replaces the original file on save. This protocol exists to reduce risk of data loss in the event of an I/O error on save.

添加set nowritebackup只是在保存时替换原始文件。该协议的存在是为了降低保存时发生 I/O 错误时数据丢失的风险。

回答by Mushr00m

I add the same problem in Espresso and you can "fix" it in Gulp by using the debounceDelay option like this :

我在 Espresso 中添加了同样的问题,你可以通过使用 debounceDelay 选项在 Gulp 中“修复”它,如下所示:

gulp.watch('/**/*.less', {debounceDelay: 2000}, ['less']);

That did the trick for me. But it's a pain to add it to every gulp.watch I don't know if we can put this option globaly...

那对我有用。但是将它添加到每个 gulp.watch 中我不知道我们是否可以将这个选项全局化......

回答by Trisha Crowley

This worked for me

这对我有用

.pipe(watch('/**/*.less', { awaitWriteFinish: true }))

https://github.com/paulmillr/chokidar#api

https://github.com/paulmillr/chokidar#api

回答by MattDiMu

Hint: the debounce parameter only works for the SAME file/event. If multiple events/files change, it won't help. Sometimes (e.g. I copied files into the a directory being served by my local server) gulp-cachedmight help, sometimes excluding certain files/patterns (e.g. the sourcemaps files) might help (use ! to negate the selection). e.g.

提示:去抖动参数仅适用于相同的文件/事件。如果多个事件/文件更改,则无济于事。有时(例如,我将文件复制到由本地服务器提供服务的目录中)gulp-cached可能会有所帮助,有时排除某些文件/模式(例如 sourcemaps 文件)可能会有所帮助(使用 ! 来否定选择)。例如

gulp.watch(['js/**/*', '!js/**/*.map'])

回答by OverZealous

You should be able to use gulp-batchto batch the changes, since it has a debounceoption.

您应该能够使用gulp-batch批量更改更改,因为它有一个debounce选项。

Something like this:

像这样的东西:

gulp.src(['server/**/*.js'], batch({debounce: 50}, function(events) {
    return events
        .pipe(...); // your code here
}));

回答by Stphane

One year later ...

一年之后 ...

Using

使用

  • nodejs0.10.25
  • gulp3.8.10
  • 节点0.10.25
  • 吞咽3.8.10

Gaz debounceDelayoption did not change anything for me, neither did I understand how to use gulp-batch callback argument :/...

GazdebounceDelay选项对我没有任何改变,我也不明白如何使用 gulp-batch 回调参数:/......

To avoid consecutives task calls after several files have been changed, I used the oldschool setTimeout function:

为了避免在更改多个文件后连续调用任务,我使用了 oldschool setTimeout 函数:

// ...
var
SRC = ['js/*.js', '!js/*.min.js'], DEST = 'js',
processJs = function(){
    util.log('Processing: ['+ SRC.join(' | ') +']');
    var stream = gulp.src(SRC)
        .pipe(uglify())
        .pipe(concat('scripts.min.js'))
        .pipe(gulp.dest(DEST));
    return stream;
};


gulp.task('default', function(){
    var delay = 2000, timer,
        watcher = gulp.watch(
            SRC,
            // Callback triggered whatever the event type is (added / changed / deleted)
            function(event) { // .path | .type
                // If the timer was assigned a timeout id few time ago..
                // Prevent last postpone task to be run
                if(timer){
                    clearTimeout(timer);
                }
                // Postpone the task
                timer = setTimeout(
                    function(){processJs();timer=0;}
                    ,delay
                );
            }
        );
    util.log("/!\ Watching job "+ Array(25).join('~'));
});

回答by Alexander Schmidt

Had the same issue and it turns out, that gulp-sourcemaps causes it (see -> Using source maps causes task to run twice)

有同样的问题,结果是 gulp-sourcemaps 导致它(请参阅 -> 使用源映射导致任务运行两次

Get a solution with gulp-notify and the attribute onLast:

使用 gulp-notify 和 onLast 属性获取解决方案:

.pipe(notify({message: 'YOUR MESSAGE', onLast: true}));

回答by LukeAskew

I was seeing a similar issue, but it was caused by having the page open in multiple tabs/windows.

我看到了类似的问题,但这是由于在多个选项卡/窗口中打开页面造成的。

回答by Peheje

I tried debounce and awaitWriteFinish. It didn't work. This did:

我试过 debounce 和 awaitWriteFinish。它没有用。这做到了:

const gulp = require("gulp");
const exec = require('child_process').exec;
let run = false;

gulp.task("watch", () => {
  console.log("watching ..");
  gulp.watch("**/*.js", ["browserify"]);
});

gulp.task("browserify", () => {
  if (run) { return; }
  run = true;
  console.log("calling browserify");
  exec("browserify app.js -o bundle.js");
  setTimeout(() => {
    run = false;
  }, 1000);
});