Gulp-Fehler: Die folgenden Aufgaben wurden nicht ausgeführt: Haben Sie vergessen, den asynchronen Abschluss zu signalisieren?

211

Ich habe die folgenden gulpfile.js , die ich über die Befehlszeile gulp message ausführe :

var gulp = require('gulp');

gulp.task('message', function() {
  console.log("HTTP Server Started");
});

Ich erhalte die folgende Fehlermeldung:

[14:14:41] Using gulpfile ~\Documents\node\first\gulpfile.js
[14:14:41] Starting 'message'...
HTTP Server Started
[14:14:41] The following tasks did not complete: message
[14:14:41] Did you forget to signal async completion?

Ich verwende gulp 4 auf einem Windows 10-System. Hier ist die Ausgabe von gulp --version:

[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2
John Deighan
quelle
1
Wenn Sie hier sind, weil Sie ein Problem mit haben webpack-stream. Verwenden Sie dies: github.com/shama/webpack-stream/issues/…
B3none

Antworten:

447

Da Ihre Aufgabe möglicherweise asynchronen Code enthält, müssen Sie gulp signalisieren, wenn die Ausführung Ihrer Aufgabe abgeschlossen ist (= "asynchrone Fertigstellung").

In Gulp 3.x könnten Sie davonkommen, ohne dies zu tun. Wenn Sie nicht explizit einen asynchronen Abschluss signalisieren, geht gulp einfach davon aus, dass Ihre Aufgabe synchron ist und beendet ist, sobald Ihre Aufgabenfunktion zurückkehrt. Gulp 4.x ist in dieser Hinsicht strenger. Sie müssen den Abschluss der Aufgabe explizit signalisieren.

Sie können dies auf sechs Arten tun :

1. Geben Sie einen Stream zurück

Dies ist keine Option, wenn Sie nur versuchen, etwas zu drucken, aber es ist wahrscheinlich der am häufigsten verwendete asynchrone Abschlussmechanismus, da Sie normalerweise mit Schluck-Streams arbeiten. Hier ist ein (ziemlich ausgeklügeltes) Beispiel, das es für Ihren Anwendungsfall demonstriert:

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

gulp.task('message', function() {
  return gulp.src('package.json')
    .pipe(print(function() { return 'HTTP Server Started'; }));
});

Der wichtige Teil hier ist die returnAussage. Wenn Sie den Stream nicht zurückgeben, kann gulp nicht feststellen, wann der Stream beendet ist.

2. Geben Sie a zurück Promise

Dies ist ein viel passenderer Mechanismus für Ihren Anwendungsfall. Beachten Sie, dass Sie das PromiseObjekt die meiste Zeit nicht selbst erstellen müssen , sondern normalerweise von einem Paket bereitgestellt werden (z. B. gibt das häufig verwendete delPaket a zurück Promise).

gulp.task('message', function() { 
  return new Promise(function(resolve, reject) {
    console.log("HTTP Server Started");
    resolve();
  });
});

Mit der Async / Await- Syntax kann dies noch weiter vereinfacht werden. Alle asyncimplizit markierten Funktionen geben ein Versprechen zurück, sodass auch Folgendes funktioniert (wenn Ihre node.js-Version dies unterstützt ):

gulp.task('message', async function() {
  console.log("HTTP Server Started");
});

3. Rufen Sie die Rückruffunktion auf

Dies ist wahrscheinlich der einfachste Weg für Ihren Anwendungsfall: gulp übergibt automatisch eine Rückruffunktion als erstes Argument an Ihre Aufgabe. Rufen Sie diese Funktion einfach auf, wenn Sie fertig sind:

gulp.task('message', function(done) {
  console.log("HTTP Server Started");
  done();
});

4. Geben Sie einen untergeordneten Prozess zurück

Dies ist vor allem dann nützlich, wenn Sie ein Befehlszeilentool direkt aufrufen müssen, da kein node.js-Wrapper verfügbar ist. Es funktioniert für Ihren Anwendungsfall, aber ich würde es natürlich nicht empfehlen (zumal es nicht sehr portabel ist):

var spawn = require('child_process').spawn;

gulp.task('message', function() {
  return spawn('echo', ['HTTP', 'Server', 'Started'], { stdio: 'inherit' });
});

5. Geben Sie einen RxJS zurückObservable .

Ich habe diesen Mechanismus noch nie verwendet, aber wenn Sie RxJS verwenden, kann er nützlich sein. Es ist eine Art Overkill, wenn Sie nur etwas drucken möchten:

var of = require('rxjs').of;

gulp.task('message', function() {
  var o = of('HTTP Server Started');
  o.subscribe(function(msg) { console.log(msg); });
  return o;
});

6. Senden Sie eine EventEmitter

Wie beim vorherigen schließe ich dies der Vollständigkeit halber ein, aber es ist nicht wirklich etwas, das Sie verwenden werden, es sei denn, Sie verwenden EventEmitteraus irgendeinem Grund bereits ein .

gulp.task('message3', function() {
  var e = new EventEmitter();
  e.on('msg', function(msg) { console.log(msg); });
  setTimeout(() => { e.emit('msg', 'HTTP Server Started'); e.emit('finish'); });
  return e;
});
Sven Schönung
quelle
4
Nach ein paar Stunden googeln fand ich dieses Beispiel. Sehr hilfreich. Danke dir!
Paxtor
es ist hilfreich für mich, ths!
Anan
1
Ich freue mich sehr über Ihre Antwort. +1 große Zeit.
Konrad Viltersten
6
Ich habe Ihre elegante und informative Antwort am 17. November sehr geschätzt. Und heute, am Weihnachtstag, schätze ich es wieder. Dies ist einer der Fälle, in denen ich wünschte, ich könnte +2 vergeben ... Ich kann nicht glauben, dass die Goolearching diesen Link nicht als Top 1 herausstellt, wenn nach " Die folgenden Aufgaben wurden nicht abgeschlossen " oder " Haben Sie " gesucht Vergessen Sie, den asynchronen Abschluss zu signalisieren? "...
Konrad Viltersten
"Das häufig verwendete del-Paket gibt ein Versprechen zurück". Ich benutze del. Wie schreibe ich meinen Schluckcode, um das Versprechen zu nutzen? (PS. Absolut erstaunliche Antwort! +1)
Daniel Tonon
84

Ein Problem mit Gulp 4 .

Versuchen Sie zur Lösung dieses Problems, Ihren aktuellen Code zu ändern:

gulp.task('simpleTaskName', function() {
  // code...
});

zum Beispiel in diese:

gulp.task('simpleTaskName', async function() {
  // code...
});

oder hinein:

gulp.task('simpleTaskName', done => {
  // code...
  done();
});
simhumileco
quelle
2
Der fehlende Anruf war mein Problem. Vielen Dank für Ihre Antwort!
Marco Santarossa
1
Beachten Sie jedoch, dass Pfeilfunktionen keinen separaten Bereich haben.
JepZ
19

Das hat funktioniert!

gulp.task('script', done => {
    // ... code gulp.src( ... )
    done();
});

gulp.task('css', done => {
    // ... code gulp.src( ... )
    done();
});

gulp.task('default', gulp.parallel(
        'script',
        'css'
  )
);
Khachornchit Songsaen
quelle
2
Dies ist die beste Antwort
Văn Quyết
13

Beim Versuch, einen sehr einfachen SASS / CSS- Build auszuführen, wurde derselbe Fehler angezeigt .

Meine Lösung (die dieselben oder ähnliche Fehler beheben kann) bestand darin, einfach doneeinen Parameter in die Standardaufgabenfunktion einzufügen und ihn am Ende der Standardaufgabe aufzurufen:

// Sass configuration
var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('sass', function () {
    gulp.src('*.scss')
        .pipe(sass())
        .pipe(gulp.dest(function (f) {
            return f.base;
        }))
});

gulp.task('clean', function() {
})

gulp.task('watch', function() {
    gulp.watch('*.scss', ['sass']);
})


gulp.task('default', function(done) { // <--- Insert `done` as a parameter here...
    gulp.series('clean','sass', 'watch')
    done(); // <--- ...and call it here.
})

Hoffe das hilft!

KLPA
quelle
7
Schön, ein Beispiel mit tatsächlichen Aufgabeninhalten zu sehen
Jonathan
8

Sie müssen zwei Dinge tun:

  1. asyncVor Funktion hinzufügen .
  2. Starten Sie Ihre Funktion mit return.

    var gulp = require('gulp');
    
    gulp.task('message', async function() {
        return console.log("HTTP Server Started");
    });
Majali
quelle
7

Ich kann nicht behaupten, diesbezüglich sehr gut informiert zu sein, aber ich hatte das gleiche Problem und habe es gelöst.

Es gibt eine 7. Möglichkeit, dies mithilfe einer asynchronen Funktion zu beheben .

Schreiben Sie Ihre Funktion, aber fügen Sie das asynchrone Präfix hinzu .

Auf diese Weise verpackt Gulp die Funktion in ein Versprechen und die Aufgabe wird fehlerfrei ausgeführt.

Beispiel:

async function() {
  // do something
};

Ressourcen:

  1. Letzter Abschnitt auf der Gulp- Seite Async Completion : Verwenden von async / await .

  2. Mozilla- asynchrone Funktionsdokumente .

Jonny
quelle
7

Dies ist ein Problem bei der Migration von gulp Version 3 auf 4. Sie können einfach einen Parameter zur Rückruffunktion hinzufügen, siehe Beispiel,

   const gulp = require("gulp")

    gulp.task("message", function(done) {
      console.log("Gulp is running...")
      done()
    });
Moftah
quelle
5

Problemumgehung: Wir müssen die Rückruffunktionen (Task und Anonymous) aufrufen:

function electronTask(callbackA)
{
    return gulp.series(myFirstTask, mySeccondTask, (callbackB) =>
    {
        callbackA();
        callbackB();
    })();    
}
Jackes David Lemos
quelle
2

Los geht's: Keine synchronen Aufgaben .

Keine synchronen Aufgaben

Synchrone Aufgaben werden nicht mehr unterstützt. Sie führten oft zu subtilen Fehlern, die schwer zu debuggen waren, z. B. das Vergessen, Ihre Streams von einer Aufgabe zurückzugeben.

Wenn Sie die Did you forget to signal async completion?Warnung sehen, wurde keine der oben genannten Techniken verwendet. Sie müssen den Fehler-First-Rückruf verwenden oder einen Stream, ein Versprechen, einen Ereignisemitter, einen untergeordneten Prozess oder eine beobachtbare Datei zurückgeben, um das Problem zu beheben.

Verwenden von async/await

Wenn Sie keine der vorherigen Optionen verwenden, können Sie Ihre Aufgabe als eine definieren async function, die Ihre Aufgabe in ein Versprechen einschließt . Auf diese Weise können Sie mit Versprechungen synchron arbeiten awaitund anderen synchronen Code verwenden.

const fs = require('fs');

async function asyncAwaitTask() {
  const { version } = fs.readFileSync('package.json');
  console.log(version);
  await Promise.resolve('some result');
}

exports.default = asyncAwaitTask;
Lloyd Apter
quelle
2

Grundsätzlich war v3.X einfacher, aber v4.x ist bei diesen Mitteln für synchrone und asynchrone Aufgaben streng.

Das asynchrone / Warten ist eine ziemlich einfache und hilfreiche Methode, um den Workflow und das Problem zu verstehen.

Verwenden Sie diesen einfachen Ansatz

const gulp = require('gulp')

gulp.task('message',async function(){
return console.log('Gulp is running...')
})
Naveen Nirban Yadav
quelle
1

Ich hatte kürzlich Probleme damit und fand den richtigen Weg, um eine defaultAufgabe zu erstellen , die sassdann ausgeführt wird sass:watch:

gulp.task('default', gulp.series('sass', 'sass:watch'));
Howard M. Lewis Schiff
quelle
1

Meine Lösung: Alles asynchronisieren und auf einen Schluck warten.

async function min_css() {
    return await gulp
        .src(cssFiles, { base: "." })
        .pipe(concat(cssOutput))
        .pipe(cssmin())
        .pipe(gulp.dest("."));
}

async function min_js() {
    return await gulp
        .src(jsFiles, { base: "." })
        .pipe(concat(jsOutput))
        .pipe(uglify())
        .pipe(gulp.dest("."));  
}

const min = async () => await gulp.series(min_css, min_js);

exports.min = min;
Kat Lim Ruiz
quelle
0

Hinzufügen als Parameter in der Standardfunktion hinzugefügt. Das wird reichen.

bmayur
quelle
0

Für diejenigen, die versuchen, gulp für die prahlerische lokale Bereitstellung zu verwenden, hilft der folgende Code

var gulp = require("gulp");
var yaml = require("js-yaml");
var path = require("path");
var fs = require("fs");

//Converts yaml to json
gulp.task("swagger", done => {
    var doc = yaml.safeLoad(fs.readFileSync(path.join(__dirname,"api/swagger/swagger.yaml")));
    fs.writeFileSync(
        path.join(__dirname,"../yourjsonfile.json"),
        JSON.stringify(doc, null, " ")
        );
    done();
});

//Watches for changes    
gulp.task('watch', function() {
  gulp.watch('api/swagger/swagger.yaml', gulp.series('swagger'));  
});
hellowahab
quelle
0

Für mich war das Problem anders: Angular-cli wurde nicht installiert (ich habe eine neue Node-Version mit NVM installiert und einfach vergessen, zu installieren).

Sie können die Ausführung von "ng version" überprüfen.

Wenn Sie es nicht haben, führen Sie einfach "npm install -g @ angle / cli" aus.

Ari Waisberg
quelle
0

Sie müssen eines tun:

  • asyncVor Funktion hinzufügen .

const gulp = require('gulp');

gulp.task('message', async function() {
    console.log("Gulp is running...");
});

Chinthani Sugandhika
quelle