Errore Gulp: le seguenti attività non sono state completate: hai dimenticato di segnalare il completamento asincrono?


212

Ho il seguente gulpfile.js , che sto eseguendo tramite il messaggio gulp della riga di comando :

var gulp = require('gulp');

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

Ricevo il seguente messaggio di errore:

[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?

Sto usando gulp 4 su un sistema Windows 10. Ecco l'output di gulp --version:

[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2

1
Se sei qui perché hai un problema con webpack-stream. Usa questo: github.com/shama/webpack-stream/issues/…
B3none

Risposte:


447

Poiché l'attività potrebbe contenere codice asincrono, è necessario segnalare gulp al termine dell'esecuzione dell'attività (= "completamento asincrono").

In Gulp 3.x potresti cavartela senza farlo. Se non si segnalasse esplicitamente il completamento asincrono, gulp supponerebbe semplicemente che l'attività è sincrona e che sia terminata non appena la funzione dell'attività ritorna. Gulp 4.x è più rigoroso in questo senso. Si deve segnalare in modo esplicito completamento delle attività.

Puoi farlo in sei modi :

1. Restituisce uno stream

Questa non è davvero un'opzione se stai solo cercando di stampare qualcosa, ma è probabilmente il meccanismo di completamento asincrono più frequentemente utilizzato poiché di solito stai lavorando con gulp stream. Ecco un esempio (piuttosto elaborato) che lo dimostra per il tuo caso d'uso:

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

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

La parte importante qui è la returndichiarazione. Se non restituisci lo stream, gulp non può determinare quando lo stream è terminato.

2. Restituisci a Promise

Questo è un meccanismo molto più adatto al tuo caso d'uso. Nota che la maggior parte delle volte non dovrai creare il filePromise oggetto da soli, in genere verrà fornito da un pacchetto (ad esempio il delpacchetto utilizzato di frequente restituisce a Promise).

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

Utilizzando async / await sintassi questo può essere ulteriormente semplificato. Tutte le funzioni contrassegnate asyncimplicitamente restituiscono una Promessa in modo che anche le seguenti funzioni (se la versione di node.js la supporta ):

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

3. Chiamare la funzione di richiamata

Questo è probabilmente il modo più semplice per il tuo caso d'uso: gulp passa automaticamente una funzione di callback al tuo compito come primo argomento. Basta chiamare quella funzione quando hai finito:

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

4. Restituire un processo figlio

Ciò è utile soprattutto se è necessario richiamare direttamente uno strumento da riga di comando perché non è disponibile alcun wrapper node.js. Funziona per il tuo caso d'uso, ma ovviamente non lo consiglierei (soprattutto perché non è molto portatile):

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

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

5. Restituire un RxJSObservable .

Non ho mai usato questo meccanismo, ma se stai usando RxJS potrebbe essere utile. È un po 'eccessivo se vuoi solo stampare qualcosa:

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. Restituire un EventEmitter

Come il precedente lo sto includendo per completezza, ma non è davvero qualcosa che userete a meno che non lo stiate già usando EventEmitterper qualche motivo.

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

4
Dopo un paio d'ore di googling, ho trovato questo esempio. Molto utile. Grazie!
paxtor,

è utile per me, questo!
Anan,

1
Apprezzo molto la tua risposta. +1 alla grande.
Konrad Viltersten,

6
Ho apprezzato la tua risposta elegante e istruttiva il 17 novembre. E oggi, il giorno di Natale, lo apprezzo ancora una volta. Questo è uno dei casi in cui vorrei poter assegnare +2 ... Non riesco a credere che goolearching non inserisca questo link tra i primi # 1 quando si cerca " I seguenti compiti non sono stati completati " o " Hai dimentica di segnalare il completamento asincrono? "...
Konrad Viltersten,

"il pacchetto del usato di frequente restituisce una promessa". Sto usando del, come faccio a scrivere il mio codice gulp per approfittare della promessa però? (PS. Risposta assolutamente incredibile! +1)
Daniel Tonon,

84

Un problema con Gulp 4 .

Per risolvere questo problema prova a cambiare il tuo codice attuale:

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

per esempio in questo:

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

o in questo:

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

2
La chiamata mancante da fare era il mio problema. La ringrazio per la risposta!
Marco Santarossa,

1
Tuttavia, tenere presente che le funzioni freccia non hanno un ambito separato.
JepZ,

19

Questo ha funzionato!

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

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

gulp.task('default', gulp.parallel(
        'script',
        'css'
  )
);

2
questa è la risposta migliore
Văn Quyết

13

Stavo ottenendo lo stesso errore nel tentativo di eseguire un SASS / CSS molto semplice build .

La mia soluzione (che può risolvere questi stessi errori o simili) era semplicemente quella di aggiungere donecome parametro nella funzione dell'attività predefinita e di chiamarlo alla fine dell'attività predefinita:

// 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.
})

Spero che questo ti aiuti!


7
Bello vedere un esempio con i contenuti effettivi dell'attività
Jonathan,

8

Devi fare due cose:

  1. Aggiungi asyncprima della funzione.
  2. Inizia la tua funzione con return.

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

7

Non posso affermare di essere molto ben informato su questo, ma ho avuto lo stesso problema e l'ho risolto.

C'è un 7 ° modo per risolvere questo problema, usando una funzione asincrona .

Scrivi la tua funzione ma aggiungi il prefisso asincrono .

In questo modo Gulp avvolge la funzione in una promessa e l'attività verrà eseguita senza errori.

Esempio:

async function() {
  // do something
};

risorse:

  1. Ultima sezione della pagina Gulp Completamento asincrono : utilizzo di asincrono / wait .

  2. Mozilla async funziona documenti .


7

Questo è un problema durante la migrazione da gulp versione 3 a 4, semplicemente puoi aggiungere un parametro fatto alla funzione di richiamata, vedi esempio,

   const gulp = require("gulp")

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

5

Soluzione alternativa: è necessario chiamare le funzioni di callback (Attività e Anonimo):

function electronTask(callbackA)
{
    return gulp.series(myFirstTask, mySeccondTask, (callbackB) =>
    {
        callbackA();
        callbackB();
    })();    
}

2

Ecco qui: nessuna attività sincrona .

Nessuna attività sincrona

Le attività sincrone non sono più supportate. Spesso hanno portato a sottili errori che erano difficili da eseguire il debug, come dimenticare di restituire i flussi da un'attività.

Quando viene visualizzato l' Did you forget to signal async completion?avviso, nessuna delle tecniche sopra menzionate è stata utilizzata. Per risolvere il problema, dovrai utilizzare la richiamata con errore iniziale o restituire un flusso, promessa, emettitore di eventi, processo figlio o osservabile.

Utilizzando async/await

Quando non si utilizza nessuna delle opzioni precedenti, è possibile definire l'attività come async function, che avvolge l'attività in una promessa . Questo ti permette di lavorare con le promesse in modo sincrono usando awaite usando altro codice sincrono.

const fs = require('fs');

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

exports.default = asyncAwaitTask;

2

Fondamentalmente v3.X era più semplice ma v4.x è rigoroso in questi mezzi di attività sincrone e asincrone.

L' asincero / aspetta è molto semplice e modo utile per capire il flusso di lavoro e problema.

Usa questo semplice approccio

const gulp = require('gulp')

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

1

Di recente ho avuto difficoltà con questo, e ho trovato il modo giusto per creare defaultun'attività che viene eseguita in sassquel momento sass:watch:

gulp.task('default', gulp.series('sass', 'sass:watch'));

1

La mia soluzione: metti tutto con asincrono e attendi un sorso.

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;

1

Devi fare una cosa:

  • Aggiungi asyncprima della funzione.

const gulp = require('gulp');

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


0

Aggiungi fatto come parametro nella funzione predefinita. Questo funzionerà.


0

Per coloro che stanno cercando di utilizzare gulp per una distribuzione locale spavalderia, il seguente codice sarà di aiuto

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

0

Per me il problema era diverso: Angular-cli non era installato (ho installato una nuova versione di Node usando NVM e ho semplicemente dimenticato di reinstallare angular cli)

Puoi controllare l'esecuzione di "ng version".

Se non lo hai, esegui "npm install -g @ angular / cli"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.