防止错误打破/碰撞吞噬手表

我正在运行gulp 3.6.2,并从网上的一个示例中build立了以下任务

gulp.task('watch', ['default'], function () { gulp.watch([ 'views/**/*.html', 'public/**/*.js', 'public/**/*.css' ], function (event) { return gulp.src(event.path) .pipe(refresh(lrserver)); }); gulp.watch(['./app/**/*.coffee'],['scripts']); gulp.watch('./app/**/*.scss',['scss']); }); 

任何时候,在我的CoffeeScript吞吐手表出现错误的时候,显然不是我想要的。

正如其他地方所build议的,我试过

 gulp.watch(['./app/**/*.coffee'],['scripts']).on('error', swallowError); gulp.watch('./app/**/*.scss',['scss']).on('error', swallowError); function swallowError (error) { error.end(); } 

但似乎并不奏效。

我究竟做错了什么?


为了回应@Aperçu的回答,我修改了我的swallowError方法,并试着改为:

 gulp.task('scripts', function () { gulp.src('./app/script/*.coffee') .pipe(coffee({ bare: true })) .pipe(gulp.dest('./public/js')) .on('error', swallowError); }); 

重新启动,然后在我的咖啡文件中创build一个语法错误。 同样的问题:

 [gulp] Finished 'scripts' after 306 μs stream.js:94 throw er; // Unhandled stream error in pipe. ^ Error: W:\bariokart\app\script\trishell.coffee:5:1: error: unexpected * * ^ at Stream.modifyFile (W:\bariokart\node_modules\gulp-coffee\index.js:37:33) at Stream.stream.write (W:\bariokart\node_modules\gulp-coffee\node_modules\event-stream\node_modules\through\index.js:26:11) at Stream.ondata (stream.js:51:26) at Stream.EventEmitter.emit (events.js:95:17) at queueData (W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:43:21) at next (W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:71:7) at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\map-stream\index.js:85:7 at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\lib\src\bufferFile.js:8:5 at fs.js:266:14 at W:\bariokart\node_modules\gulp\node_modules\vinyl-fs\node_modules\graceful-fs\graceful-fs.js:104:5 at Object.oncomplete (fs.js:107:15) 

你的swallowError函数应该是这样的:

 function swallowError (error) { // If you want details of the error in the console console.log(error.toString()) this.emit('end') } 

我认为你必须绑定这个函数的任务,而不是watch任务的error事件,因为这不是问题出在哪里,你应该在每个可能失败的任务上设置这个错误callback,比如当插件崩溃的时候你错过了一个; 或别的什么东西,以防止watch任务停止。

例子 :

 gulp.task('all', function () { gulp.src('./app/script/*.coffee') .pipe(coffee({ bare: true })) .on('error', swallowError) .pipe(gulp.dest('./public/js')) gulp.src('css/*.scss') .pipe(sass({ compass: true })) .on('error', swallowError) .pipe(cssmin()) .pipe(gulp.dest('dist')) }) 

或者,如果您不介意包含其他模块,则可以使用gulpfile -util日志function来防止在您的gulpfile声明一个额外的函数:

 .on('error', gutil.log) 

但是我可能会推荐看一下真棒吞咽插件插件,它用于删除error事件的onerror处理程序,导致stream的中断。 它使用起来非常简单,它阻止了你捕捉所有可能失败的任务。

 gulp.src('./app/script/*.coffee') .pipe(plumber()) .pipe(coffee({ bare: true })) .pipe(gulp.dest('./public/js')) 

有关此插件的创build者在本文中的更多信息。

上面的例子不适合我。 但是下面做了:

 var plumber = require('gulp-plumber'); var liveReload = require('gulp-livereload'); var gutil = require('gulp-util'); var plumber = require('gulp-plumber'); var compass = require('gulp-compass'); var rename = require('gulp-rename'); var minifycss = require('gulp-minify-css'); var notify = require('gulp-notify'); gulp.task('styles', function () { //only process main.scss which imports all other required styles - including vendor files. return gulp.src('./assets/scss/main.scss') .pipe(plumber(function (error) { gutil.log(error.message); this.emit('end'); })) .pipe(compass({ config_file: './config.rb', css: './css' , sass: './assets/scss' })) //minify files .pipe(rename({suffix: '.min'})) .pipe(minifycss()) //output .pipe(gulp.dest('./css')) .pipe(notify({message: 'Styles task complete'})); }); gulp.task('watch', function () { liveReload.listen(); gulp.watch('assets/scss/**/*.scss', ['styles']); }); 

用一种格式的文件

(例如:* .coffee)

如果你只想用一种格式的文件工作,那么gulp-plumber就是你的解决scheme。

例如,富处理错误和咖啡脚本警告:

 gulp.task('scripts', function() { return gulp.src(['assets/scripts/**/*.coffee']) .pipe(plumber()) .pipe(coffeelint()) .pipe(coffeelint.reporter()) .pipe(lintThreshold(10, 0, lintThresholdHandler)) .pipe(coffee({ bare: true })) .on('error', swallowError) .pipe(concat('application.js')) .pipe(gulp.dest('dist/scripts')) .pipe(rename({ suffix: '.min' })) .pipe(uglify()) .pipe(gulp.dest('dist/scripts')) .pipe(notify({ message: 'Scripts task complete' })); }); 

使用多种types的文件格式

(例如:* .coffee和* .js同时)

但是,如果您不想使用多种types的文件格式(例如: *.js*.coffee ),那么我将发布我的解决scheme。

我只会在这里发表一个自我解释的代码,之前有一些描述。

 gulp.task('scripts', function() { // plumber don't fetch errors inside gulpif(.., coffee(...)) while in watch process return gulp.src(['assets/scripts/**/*.js', 'assets/scripts/**/*.coffee']) .pipe(plumber()) .pipe(gulpif(/[.]coffee$/, coffeelint())) .pipe(coffeelint.reporter()) .pipe(lintThreshold(10, 0, lintThresholdHandler)) .pipe(gulpif(/[.]coffee$/, coffee({ // if some error occurs on this step, plumber won't catch it bare: true }))) .on('error', swallowError) .pipe(concat('application.js')) .pipe(gulp.dest('dist/scripts')) .pipe(rename({ suffix: '.min' })) .pipe(uglify()) .pipe(gulp.dest('dist/scripts')) .pipe(notify({ message: 'Scripts task complete' })); }); 

我用gulp.watch(... gulp-plumbergulp.watch(...gulp.watch(...这个问题gulp-if使用gulp.watch(...

在这里看到相关的问题: https : //github.com/floatdrop/gulp-plumber/issues/23

所以对我来说最好的select是:

  • 每个部分作为文件,并连接在一起 。 创build多个任务,可以在单独的文件中处理每个部分(如grunt),并连接它们
  • 每个部分作为stream,并合并后的stream 。 合并两个stream使用merge-stream (这是从event-stream )成一个,并继续工作(我先试了,它对我来说工作得很好,所以它比以前更快的解决scheme)

每个部分作为stream,并合并后的stream

她是我的代码的主要部分:

 gulp.task('scripts', function() { coffeed = gulp.src(['assets/scripts/**/*.coffee']) .pipe(plumber()) .pipe(coffeelint()) .pipe(coffeelint.reporter()) .pipe(lintThreshold(10, 0, lintThresholdHandler)) .pipe(coffee({ bare: true })) .on('error', swallowError); jsfiles = gulp.src(['assets/scripts/**/*.js']); return merge([jsfiles, coffeed]) .pipe(concat('application.js')) .pipe(gulp.dest('dist/scripts')) .pipe(rename({ suffix: '.min' })) .pipe(uglify()) .pipe(gulp.dest('dist/scripts')) .pipe(notify({ message: 'Scripts task complete' })); }); 

每个部分作为文件,并连接在一起

如果要把它分成几部分,那么在每个部分都应该有一个结果文件被创build。 例如:

 gulp.task('scripts-coffee', function() { return gulp.src(['assets/scripts/**/*.coffee']) .pipe(plumber()) .pipe(coffeelint()) .pipe(coffeelint.reporter()) .pipe(lintThreshold(10, 0, lintThresholdHandler)) .pipe(coffee({ bare: true })) .on('error', swallowError) .pipe(concat('application-coffee.js')) .pipe(gulp.dest('dist/scripts')); }); gulp.task('scripts-js', function() { return gulp.src(['assets/scripts/**/*.js']) .pipe(concat('application-coffee.js')) .pipe(gulp.dest('dist/scripts')); }); gulp.task('scripts', ['scripts-js', 'scripts-coffee'], function() { var re = gulp.src([ 'dist/scripts/application-js.js', 'dist/scripts/application-coffee.js' ]) .pipe(concat('application.js')) .pipe(gulp.dest('dist/scripts')) .pipe(rename({ suffix: '.min' })) .pipe(uglify()) .pipe(gulp.dest('dist/scripts')) .pipe(notify({ message: 'Scripts task complete' })); del(['dist/scripts/application-js.js', 'dist/scripts/application-coffee.js']); return re; }); 

PS:

这里使用的节点模块和function:

 // Load plugins var gulp = require('gulp'), uglify = require('gulp-uglify'), rename = require('gulp-rename'), concat = require('gulp-concat'), notify = require('gulp-notify'), plumber = require('gulp-plumber'), merge = require('ordered-merge-stream'), replace = require('gulp-replace'), del = require('del'), gulpif = require('gulp-if'), gulputil = require('gulp-util'), coffee = require('gulp-coffee'), coffeelint = require('gulp-coffeelint), lintThreshold = require('gulp-coffeelint-threshold'); var lintThresholdHandler = function(numberOfWarnings, numberOfErrors) { var msg; gulputil.beep(); msg = 'CoffeeLint failure; see above. Warning count: '; msg += numberOfWarnings; msg += '. Error count: ' + numberOfErrors + '.'; gulputil.log(msg); }; var swallowError = function(err) { gulputil.log(err.toString()); this.emit('end'); }; 

作为https://github.com/gulpjs/gulp/issues/71的一种解决方法,我已经实施了以下hack:;

 // Workaround for https://github.com/gulpjs/gulp/issues/71 var origSrc = gulp.src; gulp.src = function () { return fixPipe(origSrc.apply(this, arguments)); }; function fixPipe(stream) { var origPipe = stream.pipe; stream.pipe = function (dest) { arguments[0] = dest.on('error', function (error) { var state = dest._readableState, pipesCount = state.pipesCount, pipes = state.pipes; if (pipesCount === 1) { pipes.emit('error', error); } else if (pipesCount > 1) { pipes.forEach(function (pipe) { pipe.emit('error', error); }); } else if (dest.listeners('error').length === 1) { throw error; } }); return fixPipe(origPipe.apply(this, arguments)); }; return stream; } 

将它添加到你的gulpfile.js并使用它:

 gulp.src(src) // ... .pipe(uglify({compress: {}})) .pipe(gulp.dest('./dist')) .on('error', function (error) { console.error('' + error); }); 

这感觉就像是对我来说最自然的error handling。 如果没有error handling程序,它将会抛出一个错误。 testing节点v0.11.13。

打字稿

这是为我工作。 我使用Typescript和分隔function(以避免与this关键字混淆)处理less 。 这也适用于Javascript

 var gulp = require('gulp'); var less = require('gulp-less'); gulp.task('less', function() { // writing a function to avoid confusion of 'this' var l = less({}); l.on('error', function(err) { // ***** // Handle the error as you like // ***** l.emit('end'); }); return gulp .src('path/to/.less') .pipe(l) .pipe(gulp.dest('path/to/css/output/dir')) }) 

现在,当你watch .less文件,并发生errorwatch不会停止,新的更改将按照您的less task

:我试着用l.end(); ; 但是,它没有工作。 但是, l.emit('end'); 完全有效。

希望这个帮助。 祝你好运。

一个简单的解决scheme就是在一个Bash(或者sh)shell中将gulp watch放在一个无限循环中。

while true; do gulp; gulp watch; sleep 1; done

在编辑JavaScript时,将此命令的输出保持在屏幕上的可见区域。 当您的编辑导致错误时,Gulp将崩溃,打印堆栈跟踪,等待一秒钟,然后继续观看源文件。 然后,您可以更正语法错误,Gulp会通过打印出正常的输出或者再次崩溃(然后恢复)来指示编辑是否成功。

这将在Linux或Macterminal工作。 如果您使用Windows,请使用Cygwin或Ubuntu Bash(Windows 10)。

这对我有用 – >

 var gulp = require('gulp'); var sass = require('gulp-sass'); gulp.task('sass', function(){ setTimeout(function(){ return gulp.src('sass/*.sass') .pipe(sass({indentedSyntax: true})) .on('error', console.error.bind(console)) .pipe(gulp.dest('sass')); }, 300); }); gulp.task('watch', function(){ gulp.watch('sass/*.sass', ['sass']); }); gulp.task('default', ['sass', 'watch']) 

我只是添加了.on('error',console.error.bind(console))行,但是我必须以root身份运行gulp命令。 我在一个PHP应用程序运行节点吞咽,所以我有一个服务器上的多个帐户,这就是为什么我遇到了吞咽打破语法错误的问题,因为我没有作为根运行gulp …也许水pipe工和一些如果我以root身份运行,这里的其他答案会对我有用。 感谢Accio Code https://www.youtube.com/watch?v=iMR7hq4ABOw获取答案。; 他说,通过处理这个错误,它可以帮助你确定错误是在哪里,在控制台中是什么,也可以避免吞咽语法错误。 他说这是一个轻量级的解决scheme,所以不知道它是否适用于你正在寻找的东西。 快速修复,但值得一试。 希望这可以帮助别人!

最简单的方法while [ 1 ]; do gulp watch; sleep 0; done while [ 1 ]; do gulp watch; sleep 0; done while [ 1 ]; do gulp watch; sleep 0; done