Gulp错误:以下任务未完成:您是否忘记发出异步完成信号?

问题描述 投票:139回答:9

我有以下gulpfile.js,我正在通过命令行“gulp message”执行:

var gulp = require('gulp');

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

我收到以下错误消息:

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

我在Windows 10系统上使用gulp 4。这是gulp --version的输出:

[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2
gulp
9个回答
320
投票

由于您的任务可能包含异步代码,因此您必须在任务完成执行时发出信号(=“异步完成”)。

在Gulp 3.x中,你可以在不这样做的情况下逃脱。如果你没有明确表示异步完成gulp会假设你的任务是同步的,并且它会在你的任务函数返回后立即完成。 Gulp 4.x在这方面更加严格。您必须明确表示任务完成。

你可以在six ways做到这一点:

1. Return a Stream

如果您只是尝试打印某些东西,这不是一个真正的选项,但它可能是最常用的异步完成机制,因为您通常使用gulp流。这是一个(相当人为的)示例,演示了它的用例:

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

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

这里的重要部分是return声明。如果您不返回流,gulp无法确定流何时完成。

2. Return a Promise

这是一个更适合您的用例的机制。请注意,大多数情况下,您不必自己创建Promise对象,它通常由包提供(例如,常用的del包返回Promise)。

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

使用async/await语法可以进一步简化。标记为async的所有函数都隐式返回Promise,因此以下也适用(如果你的node.js version supports it):

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

3. Call the callback function

对于您的用例,这可能是最简单的方法:gulp会自动将回调函数作为其第一个参数传递给您的任务。完成后只需调用该函数:

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

4. Return a child process

如果您必须直接调用命令行工具,因为没有node.js包装器可用,这非常有用。它适用于您的用例,但显然我不推荐它(特别是因为它不是非常便携):

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

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

5. Return a RxJS Observable.

我从来没有使用过这种机制,但是如果你使用RxJS它可能会有用。如果你只想打印一些内容,这有点过分:

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. Return an EventEmitter

和前一个一样,为了完整起见我将它包括在内,但除非你因为某种原因已经使用了EventEmitter,否则你不会真正使用它。

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

0
投票

你需要做两件事;

  1. 在函数之前添加异步
  2. 返回时启动您的功能 var gulp = require('gulp'); gulp.task('message', async function() { return console.log("HTTP Server Started"); });

32
投票

Gulp 4的一个问题 - 您需要明确表示每个功能的任务完成。

要解决此问题,请尝试更改当前代码:

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

比如这个:

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

10
投票

这有效!

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

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

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

5
投票

我试图运行一个非常简单的SASS / CSS构建时遇到同样的错误。

我的解决方案(可以解决相同或类似的错误)只是在默认任务函数中添加'done'作为参数,并在默认任务结束时调用它:

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

希望这可以帮助!


4
投票

解决方法:我们需要调用回调函数(Task和Anonymous):

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

3
投票

我不能声称对此非常了解,但我有同样的问题,并已解决它。通过使用异步函数,有第7种方法可以解决这个问题。

编写您的函数但添加前缀async。 通过这样做,Gulp将函数包装在一个promise中,任务将运行而不会出错。

例:

async function() {
  // do something
};

资源:

关于gulp页面'async completion'的最后一节,'使用async / await':

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

Mozilla异步函数文档在这里:

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


0
投票

在默认函数中添加完成作为参数。那样做。


0
投票

对于那些试图使用gulp进行swagger本地部署的人来说,下面的代码会有所帮助

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
投票

干得好:

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

无同步任务不再支持同步任务。它们经常导致难以调试的细微错误,例如忘记从任务返回流。

当你看到“你忘了发信号异步完成吗?”警告,没有使用上述技术。您需要使用错误优先回调或返回流,promise,事件发射器,子进程或observable来解决问题。

使用async / await当不使用任何先前的选项时,您可以将任务定义为异步功能,将任务包装在承诺中。这允许您使用await同步使用promises并使用其他同步代码。

const fs = require('fs');

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

exports.default = asyncAwaitTask;
© www.soinside.com 2019 - 2024. All rights reserved.