web-dev-qa-db-fra.com

Erreur Gulp: Les tâches suivantes n'ont pas abouti: Avez-vous oublié de signaler la fin asynchrone?

J'ai le gulpfile.js suivant, que je suis en train d'exécuter via la ligne de commande "gulp message":

var gulp = require('gulp');

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

Je reçois le message d'erreur suivant:

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

J'utilise gulp 4 sur un système Windows 10. Voici le résultat de gulp --version:

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

Comme votre tâche peut contenir du code asynchrone, vous devez signaler gulp à la fin de l'exécution de votre tâche (= "achèvement asynchrone").

Dans Gulp 3.x, vous pouvez vous en sortir sans le faire. Si vous ne signaliez pas explicitement l'achèvement asynchrone, gulp supposerait simplement que votre tâche est synchrone et qu'elle est terminée dès le retour de la tâche. Gulp 4.x est plus strict à cet égard. Vous devez signaler explicitement l'achèvement de la tâche.

Vous pouvez le faire de différentes manières :

1. Renvoyer un flux

Ce n'est pas vraiment une option si vous essayez seulement d'imprimer quelque chose, mais c'est probablement le mécanisme de complétion asynchrone le plus utilisé car vous travaillez généralement avec des flux d'abeilles. Voici un exemple (plutôt artificiel) de démonstration pour votre cas d'utilisation:

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

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

La partie importante ici est la déclaration return. Si vous ne renvoyez pas le flux, gulp ne peut pas déterminer quand le flux est terminé.

2. Retourne un Promise

C'est un mécanisme bien plus adapté à votre cas d'utilisation. Notez que la plupart du temps, vous n'avez pas à créer l'objet Promise, il sera généralement fourni par un package (par exemple, le package fréquemment utilisé del renvoie un Promise.

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

L'utilisation de la syntaxe async/wait peut être simplifiée davantage. Toutes les fonctions marquées async renvoient implicitement une promesse. Par conséquent, le code suivant fonctionne également (si votre version de node.js le prend en charge ):

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

3. Appeler la fonction de rappel

C'est probablement le moyen le plus simple pour votre cas d'utilisation: gulp transmet automatiquement une fonction de rappel à votre tâche en tant que premier argument. Appelez cette fonction lorsque vous avez terminé:

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

4. Renvoyer un processus enfant

Cela est surtout utile si vous devez appeler un outil de ligne de commande directement, car aucun wrapper node.js n'est disponible. Cela fonctionne pour votre cas d'utilisation mais je ne le recommanderais évidemment pas (surtout parce que ce n'est pas très portable):

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

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

5. Renvoyez un RxJS Observable .

Je n'ai jamais utilisé ce mécanisme, mais si vous utilisez RxJS, cela pourrait être utile. C'est un peu exagéré si vous voulez juste imprimer quelque chose:

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

Comme dans le précédent, j'inclus ceci par souci d'exhaustivité, mais ce n'est pas vraiment quelque chose que vous allez utiliser sauf si vous utilisez déjà un EventEmitter pour une raison quelconque.

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;
});
349
Sven Schoenung

n problème avec Gulp 4 - vous devez explicitement signaler l'accomplissement de la tâche pour chaque fonction .

Pour résoudre ce problème, essayez de changer votre code actuel:

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

par exemple dans ceci:

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

Cela a fonctionné!

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

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

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

J'avais cette même erreur en essayant de lancer une compilation SASS/CSS très simple.

Ma solution (qui peut résoudre des erreurs identiques ou similaires) consistait simplement à ajouter "done" en tant que paramètre dans la fonction de tâche par défaut et à l'appeler à la fin de la tâche par défaut:

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

J'espère que cela t'aides!

6
KLPA

Solution: nous devons appeler les fonctions de rappel (Task et Anonymous):

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

Je ne peux pas prétendre être très au courant à ce sujet mais j'ai eu le même problème et l'ai résolu. Il existe un septième moyen de résoudre ce problème en utilisant une fonction async .

Ecrivez votre fonction mais ajoutez le préfixe async .
En faisant cela, Gulp encapsule la fonction dans une promesse et la tâche s’exécutera sans erreur.

Exemple:

async function() {
  // do something
};

Ressources:

Dernière section de la page "Extraction asynchrone" ici, "Utilisation de l'async/wait":

https://gulpjs.com/docs/fr/getting-started/async-completion

Les fonctions asynchrones de Mozilla docs ici:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

4
Jonny

Vous devez faire deux choses.

  1. Ajouter async avant la fonction
  2. Commencez votre fonction avec le retour

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

Add done en tant que paramètre dans la fonction par défaut. Cela fera l'affaire.

0
bmayur

Pour ceux qui essaient d’utiliser gulp pour un déploiement local swagger, le code suivant aidera

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
hellowahab

Voici:

https://gulpjs.com/docs/fr/getting-started/async-completion#no-synchronous-tasks

Pas de tâches synchrones Les tâches synchrones ne sont plus prises en charge. Elles conduisaient souvent à des erreurs subtiles difficiles à résoudre, telles que l’oubli de vos flux d’une tâche.

Lorsque vous voyez le message "Avez-vous oublié de signaler la fin asynchrone?" attention, aucune des techniques mentionnées ci-dessus n’a été utilisée. Pour résoudre le problème, vous devez utiliser le rappel en priorité ou renvoyer un flux, une promesse, un émetteur d'événement, un processus enfant ou observable.

Utilisation de async/wait Si vous n'utilisez aucune des options précédentes, vous pouvez définir votre tâche comme une fonction asynchrone, qui enveloppe votre tâche dans une promesse. Cela vous permet de travailler avec des promesses de manière synchrone en utilisant wait et d'utiliser un autre code synchrone.

const fs = require('fs');

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

exports.default = asyncAwaitTask;
0
Lloyd Apter