web-dev-qa-db-de.com

Verhindern Sie, dass Fehler brechen/abstürzen

Ich verwende gulp 3.6.2 und habe die folgende Aufgabe, die aus einem Online-Beispiel eingerichtet wurde

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']);
});

Jedes Mal, wenn ein Fehler in meiner CoffeeScript-Schluckuhr auftritt, ist offensichtlich nicht das, was ich will.

Wie an anderer Stelle empfohlen, habe ich dies versucht

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

aber es scheint nicht zu funktionieren.

Was mache ich falsch?


Als Antwort auf die Antwort von @ Aperçu habe ich meine swallowError-Methode geändert und stattdessen Folgendes versucht:

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

Neustart und erstellte dann einen Syntaxfehler in meiner Kaffeedatei. Gleicher Fehler:

[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)
168
George Mauer

Ihre swallowError-Funktion sollte so aussehen:

function swallowError (error) {

  // If you want details of the error in the console
  console.log(error.toString())

  this.emit('end')
}

Ich denke, Sie müssen diese Funktion an das error-Ereignis der fallenden Task binden, nicht an die watch-Task, da das Problem hier nicht auftritt. Sie sollten diesen Fehler-Callback für jede Task festlegen, die möglicherweise fehlschlägt, wie Plugins, die abbrechen Sie haben einen ; oder etwas anderes verpasst, um zu verhindern, dass watch beendet wird.

Beispiele:

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'))
})

Wenn Sie nichts dagegen haben, ein anderes Modul hinzuzufügen, können Sie die log - Funktion von gulp-util verwenden, um zu verhindern, dass Sie in Ihrer gulpfile eine zusätzliche Funktion deklarieren:

.on('error', gutil.log)

Ich kann jedoch einen Blick auf das fantastische - gulp-plumber - Plugin werfen, das zum Entfernen des onerror-Handlers des error-Ereignisses verwendet wird, wodurch die Streams unterbrochen werden. Es ist sehr einfach zu bedienen und hält Sie davon ab, alle Aufgaben zu erfassen, die möglicherweise fehlschlagen.

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

Mehr Infos dazu auf diesem Artikel vom Ersteller des betreffenden Plugins.

253
Balthazar

Die obigen Beispiele haben für mich nicht funktioniert. Folgendes tat es jedoch:

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']);
});
20
user1491819

Mit einem Dateiformat

(zB: * .coffee)

Wenn Sie nur mit einem Dateiformat arbeiten möchten, ist gulp-plumber Ihre Lösung.

Zum Beispiel reich behandelte Fehler und Warnungen beim Kaffeescripting:

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' }));
});

Mit mehreren Arten von Dateiformaten

(zB: * .coffee und * .js gleichzeitig)

Wenn Sie jedoch nicht mit mehreren Arten von Dateiformaten arbeiten (z. B. *.js und *.coffee), werde ich meine Lösung veröffentlichen.

Ich werde hier einfach einen selbsterklärenden Code posten, mit einer Beschreibung vorher.

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' }));
});

Ich habe das Problem mit gulp-plumber und gulp-if mit gulp.watch(... konfrontiert.

Siehe verwandtes Problem hier: https://github.com/floatdrop/gulp-plumber/issues/23

Die beste Option für mich war also:

  • Jeder Teil als Datei und verkettet nach. Erstellen Sie mehrere Tasks, die jedes Teil in einer separaten Datei verarbeiten können (wie bei Grunt), und verketten Sie diese
  • Jeder Teil als Stream und Zusammenführungsstreams nach. Mischen Sie zwei Streams mit merge-stream (die aus event-stream erstellt wurden) zu einem und setzen Sie den Job fort (ich habe es zuerst probiert, und es funktioniert gut für mich, sodass es eine schnellere Lösung ist als der vorherige).

Jeder Teil als Stream, und danach Streams zusammenführen

Ihr ist der Hauptteil meines Codes:

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' }));
});

Jeder Teil als Datei und verketten nach

Wenn dies in Teile unterteilt werden soll, sollte in jedem Teil eine Ergebnisdatei erstellt werden. ZB: 

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;

});

P.S .:

Hier Knotenmodule und Funktionen, die verwendet wurden:

// 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');
};
4
Roman M. Koss

Ich benutze gerne Klempner, weil er einer Aufgabe einen globalen Listener hinzufügen und eine aussagekräftige Meldung anzeigen kann. 

var plumber = require('gulp-plumber');

gulp.task('compile-scss', function () {
    gulp.src('scss/main.scss')
        .pipe(plumber())
        .pipe(sass())
        .pipe(autoprefixer())
        .pipe(cssnano())
        .pipe(gulp.dest('css/'));
});

Referenz: https://scotch.io/tutorials/prevent-errors-from-crashing-gulp-watch

3

Eine einfache Lösung dafür ist, gulp watch in eine Endlosschleife innerhalb einer Bash- (oder Sh-) Shell zu setzen.

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

Behalten Sie die Ausgabe dieses Befehls in einem sichtbaren Bereich auf Ihrem Bildschirm, wenn Sie Ihr JavaScript bearbeiten. Wenn Ihre Bearbeitungen zu einem Fehler führen, stürzt Gulp ab, druckt die Stapelablaufverfolgung, wartet eine Sekunde und nimmt die Überwachung der Quelldateien wieder auf. Sie können dann den Syntaxfehler korrigieren, und Gulp zeigt an, ob die Bearbeitung erfolgreich war oder nicht, indem Sie entweder die normale Ausgabe ausdrucken oder abstürzen (und dann wieder fortsetzen).

Dies funktioniert in einem Linux- oder Mac-Terminal. Wenn Sie Windows verwenden, verwenden Sie Cygwin oder Ubuntu Bash (Windows 10).

2
Jesse Hogan

Ich habe den folgenden Hack als Workaround für https://github.com/gulpjs/gulp/issues/71 implementiert:

// 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;
}

Fügen Sie es Ihrer Datei gulpfile.js hinzu und verwenden Sie es so:

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

Das fühlt sich für mich die natürlichste Fehlerbehandlung an. Wenn überhaupt kein Fehlerhandler vorhanden ist, wird ein Fehler ausgegeben. Getestet mit Node v0.11.13.

2
Joel Richard

TypeScript

Das hat bei mir funktioniert. Ich arbeite mit TypeScript und trenne die Funktion (um Verwechslungen mit dem this-Schlüsselwort zu vermeiden), um mit less zu arbeiten. Dies funktioniert auch mit 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'))
})

Wenn Sie nun watch.less-Dateien verwenden und eine error auftritt, wird die watch nicht angehalten und neue Änderungen werden entsprechend Ihrem less task verarbeitet.

NOTE: Ich habe es mit l.end(); versucht; es hat jedoch nicht funktioniert. l.emit('end'); funktioniert jedoch völlig.

Ich hoffe das hilft. Viel Glück.

1
Akash

Das hat für mich funktioniert ->

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'])

Ich habe gerade das .__ hinzugefügt. .on ('error', console.error.bind (console)) Zeile, aber ich musste die .__ ausführen. gulp Befehl als root. Ich verwende node gulp auf einer PHP-Anwendung, so dass ich mehrere Konten auf einem Server habe. Aus diesem Grund bin ich auf das Problem des Schluckens von Syntaxfehlern gestoßen, weil ich nicht als root ausgeführt habe ... Vielleicht Klempner und einige der Andere Antworten hier hätten für mich funktioniert, wenn ich als root ausgeführt würde . Credit to Accio Code https://www.youtube.com/watch?v=iMR7hq4ABOw für die Antwort. Er sagte, durch die Fehlerbehandlung hilft es Ihnen zu bestimmen, in welcher Zeile sich der Fehler befindet und was in der Konsole ist, aber er verhindert auch, dass Schluck bei Syntaxfehlern bricht. Er sagte, es sei eine Art leichtes Problem, also nicht sicher, ob es für das funktioniert, wonach Sie suchen. Schnelle Lösung, einen Versuch wert. Hoffe das hilft jemandem!

0
kiko carisse