Gulp.watch: Fehler richtig abfangen

    In allen modernen Frontend-Build-Systemen gibt es einen Modus, watchin dem ein spezieller Daemon gestartet wird, um Dateien unmittelbar nach dem Speichern automatisch neu zu erstellen. Es hat auch gulp.js, aber mit einigen Funktionen, die das Arbeiten etwas komplizierter machen. Die Arbeit von gulp.js basiert auf der Verarbeitung von Dateien als Streams. Und Fehler in Threads können nicht immer abgefangen werden. Wenn ein Fehler auftritt, wird eine nicht abgefangene Ausnahme ausgelöst und der Prozess wird beendet.

    Damit dies nicht passiert und der Beobachter einzelne Fehler ignorieren und beim Speichern von Dateien immer wieder ausführen kann, müssen Sie in gulp einige zusätzliche Einstellungen vornehmen, die in diesem Artikel erläutert werden.

    Was ist los?


    Lassen Sie uns zuerst sehen, was passiert und warum der Beobachter manchmal abstürzt. Wenn Sie ein Plugin für gulp schreiben, wird empfohlen, ein Ereignis auszulösen, errorwenn Fehler auftreten, während das Plugin ausgeführt wird. Aber die NodeJS-Threads, auf denen das Build-System basiert, lassen Fehler nicht unbemerkt. Wenn errorniemand das Ereignis abonniert hat, wird eine Ausnahme ausgelöst, damit die Nachricht den Benutzer genau erreicht. Infolgedessen sehen Entwickler bei der Arbeit mit gulp häufig solche Fehler

    events.js:72
        throw er; // Unhandled 'error' event
    


    Bei Verwendung von Continuious-Integration (CI) kann dies hilfreich sein, wenn für jedes Commit automatische Prüfungen gestartet werden (die Assembly ist fehlgeschlagen, der Build wurde nicht zusammengestellt, die Verantwortlichen erhalten Briefe). Aber der stetig fallende Beobachter in der lokalen Entwicklung, der ständig neu gestartet werden muss, ist ein großes Ärgernis.

    Was zu tun ist?


    Im Internet finden Sie Fragen zu diesem Thema sowohl zum Stackoverflow als auch zum Toaster . Antworten auf Fragen bieten mehrere beliebte Lösungen.

    Sie können die Veranstaltung abonnieren error:

    gulp.task('less', function() {
      return gulp.src('less/*.less')
        .pipe(less().on('error', gutil.log))
        .pipe(gulp.dest('app/css'));
    });
    


    Sie können das Plugin gulp- plumber verbinden , das sich nicht nur errorfür ein Plugin anmeldet, sondern dies auch automatisch für alle nachfolgenden Plugins durchführt, die über eine Pipe verbunden sind:

    gulp.task('less', function() {
      return gulp.src('less/*.less')
          .pipe(plumber())
        .pipe(less())
        .pipe(gulp.dest('app/css'));
    });
    


    Warum machst du das nicht?


    Das Problem scheint zwar behoben zu sein, ist es aber nicht. Jetzt werden Assemblerfehler abgefangen, wir bekommen Meldungen darüber in der Konsole, der laufende Daemon-Watcher stürzt nicht ab, aber jetzt haben wir ein neues Problem.

    Angenommen, wir haben einen CI-Server, auf dem unsere Skripte für die Berechnung erstellt werden. Damit unsere Baugruppe mit watch zusammenarbeiten kann, haben wir eine der oben genannten Lösungen angewendet. Aber jetzt stellt sich heraus, dass unser Build bei Buildfehlern immer noch als erfolgreich markiert ist. Der gulp-Befehl endet immer mit Code 0. Es stellt sich heraus, dass für die CI-Assembly keine Fehler verschluckt werden müssen. Sie können nur für den Überwachungsmodus eine eigene Fehlerbehandlungsroutine hinzufügen. Dies erschwert jedoch die Beschreibung der Baugruppe und erhöht die Wahrscheinlichkeit, einen Fehler zu machen. Glücklicherweise gibt es eine Lösung, wie die Assembly auf die gleiche Weise konfiguriert werden kann, die jedoch gleichzeitig die Arbeit sowohl im Erstellungsmodus als auch im Überwachungsmodus unterstützt.

    Lösung


    Tatsächlich versucht gulp, auf Fehler in Dateistreams zu achten. Da gulp.dest()das Ergebnis jedoch normalerweise zuletzt auf die Festplatte geschrieben wird und Fehler in Zwischen-Plugins auftreten, erreicht der Fehler nicht das Ende der Kette, sodass gulp nichts davon weiß. Betrachten Sie zum Beispiel diese Kette:

    stream1.on('error', function() { console.log('error 1') })
    stream2.on('error', function() { console.log('error 2') })
    stream3.on('error', function() { console.log('error 3') })
    stream1
       .pipe(stream2)
       .pipe(stream3);
    stream1.emit('error');
    // в консоли выведется только "error 1"
    


    Im Gegensatz zu beispielsweise Versprechen breiten sich Fehler in Threads nicht weiter entlang der Kette aus, sondern müssen in jedem Thread separat abgefangen werden. Aus diesem Grund gibt es in io.js eine Pull-Anfrage , aber in aktuellen Versionen funktioniert es nicht, den Fehler an das Ende der Kette weiterzuleiten. Daher kann gulp keine Fehler von Zwischenthreads abfangen, und dies müssen wir selbst tun.

    Gulp als Beschreibung einer Aufgabe akzeptiert jedoch nicht nur eine Funktion, die einen Stream zurückgibt, sondern auch eine reguläre Callback-Funktion, wie viele APIs in node.js. In einer solchen Funktion werden wir selbst entscheiden, wann die Aufgabe mit einem Fehler abgeschlossen wurde und wann erfolgreich:

    gulp.task('less', function(done) {
      gulp.src('less/*.less')
        .pipe(less().on('error', function(error) {
          // у нас ошибка
          done(error);
        }))
        .pipe(gulp.dest('app/css'))
        .on('end', function() {
          // у нас все закончилось успешно
          done();
        });
    });
    


    Eine solche Beschreibung der Versammlung sieht ein bisschen mehr aus, weil wir jetzt einen Teil der Arbeit für das Schlucken erledigen, aber jetzt machen wir es richtig. Und wenn Sie sich eine Hilfsfunktion wie diese schreiben , wird der Unterschied fast nicht wahrnehmbar sein:

    gulp.task('less', wrapPipe(function(success, error) {
      return gulp.src('less/*.less')
         .pipe(less().on('error', error))
         .pipe(gulp.dest('app/css'));
    }));
    


    Die richtigen Meldungen werden jedoch in der Konsole sowohl während der Entwicklung als auch während des Neuaufbaus beim Speichern und auf dem CI-Server während des Aufbaus angezeigt.

    Jetzt auch beliebt: