Ошибка глотка: Следующие задачи не были выполнены: Вы забыли сообщить об асинхронном завершении?

212

У меня есть следующий gulpfile.js , который я выполняю через сообщение gulp командной строки :

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?

Я использую gulp 4 в системе Windows 10. Вот вывод из gulp --version:

[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2
Джон Дейган
источник
1
Если вы здесь, потому что у вас есть проблема с webpack-stream. Используйте это: github.com/shama/webpack-stream/issues/…
B3none

Ответы:

447

Поскольку ваша задача может содержать асинхронный код, вы должны сигнализировать gulp, когда ваша задача завершит выполнение (= "асинхронное завершение").

В Gulp 3.x вы могли бы уйти, не делая этого. Если вы не указали явное асинхронное завершение, gulp просто предположил бы, что ваша задача является синхронной и что она завершается, как только ваша задача возвращается. Gulp 4.x более строг в этом отношении. Вы должны явно сигнализировать о завершении задачи.

Вы можете сделать это шестью способами :

1. Верните поток

На самом деле это не вариант, если вы только пытаетесь что-то напечатать, но это, вероятно, наиболее часто используемый механизм асинхронного завершения, поскольку вы обычно работаете с потоками 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. Вернуть Promise

Это гораздо более подходящий механизм для вашего случая использования. Обратите внимание, что в большинстве случаев вам не нужно создавать Promiseобъект самостоятельно, обычно он предоставляется пакетом (например, часто используемый delпакет возвращает a Promise).

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

С помощью синтаксиса async / await это может быть еще более упрощено. Все функции, помеченные asyncнеявно, возвращают Promise, поэтому также работает следующее (если ваша версия node.js поддерживает это ):

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

3. Вызвать функцию обратного вызова

Вероятно, это самый простой способ для вашего варианта использования: gulp автоматически передает функцию обратного вызова вашей задаче в качестве первого аргумента. Просто вызовите эту функцию, когда закончите:

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

4. Вернуть дочерний процесс

Это в основном полезно, если вам нужно вызывать инструмент командной строки напрямую, потому что нет доступной обертки node.js. Это работает для вашего случая использования, но, очевидно, я бы не рекомендовал его (тем более что он не очень портативный):

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

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

5. Верните RxJSObservable .

Я никогда не использовал этот механизм, но если вы используете 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. Вернуть 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;
});
Свен Шёнунг
источник
4
После нескольких часов поиска в Google я нашел этот пример. Очень полезно. Спасибо!
Paxtor
это полезно для меня, тыс!
Анан
1
Я так ценю ваш ответ. +1 большое время.
Конрад Вилтерстен
6
Я оценил ваш элегантный и информативный ответ 17 ноября. И сегодня, на Рождество, я ценю это снова и снова. Это один из случаев, когда я хотел бы получить +2 ... Я не могу поверить, что goolearching не выводит эту ссылку в топ № 1 при поиске « Следующие задачи не выполнены » или « Сделали ли вы забыли сообщить о завершении асинхронной передачи? "...
Конрад Вилтерстен
msgstr "часто используемый пакет del возвращает обещание". Я использую del, как мне написать код gulp, чтобы воспользоваться обещанием? (PS. Абсолютно удивительный ответ! +1)
Даниэль Тонон
84

Проблема с Gulp 4 .

Для решения этой проблемы попробуйте изменить свой текущий код:

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

например в это:

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

или в это:

gulp.task('simpleTaskName', done => {
  // code...
  done();
});
simhumileco
источник
2
Недостающий призыв сделать это было моей проблемой. Спасибо за ваш ответ!
Марко Сантаросса
1
Однако следует помнить, что функции стрелок не имеют отдельной области видимости.
JepZ
19

Это сработало!

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

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

gulp.task('default', gulp.parallel(
        'script',
        'css'
  )
);
Хачорнчит Songsaen
источник
2
это лучший ответ
Văn Quyết
13

Я получал ту же ошибку, пытаясь запустить очень простую сборку 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.
})

Надеюсь это поможет!

KLPA
источник
7
Приятно видеть пример с фактическим содержанием задачи
Джонатан
8

Вам нужно сделать две вещи:

  1. Добавить asyncперед функцией.
  2. Начните свою функцию с return.

    var gulp = require('gulp');
    
    gulp.task('message', async function() {
        return console.log("HTTP Server Started");
    });
Majali
источник
7

Я не могу утверждать, что я очень хорошо осведомлен в этом, но у меня была та же проблема, и я решил ее.

Есть 7-й способ решить эту проблему, используя асинхронную функцию .

Напишите свою функцию, но добавьте префикс async .

Делая это, Gulp оборачивает функцию в обещание, и задача будет выполняться без ошибок.

Пример:

async function() {
  // do something
};

Ресурсы:

  1. Последний раздел на странице Gulp Асинхронное завершение : Использование async / await .

  2. Асинхронные функции Mozilla Docs .

Jonny
источник
7

Это проблема при переходе с gulp версии 3 на 4. Просто вы можете добавить параметр, выполненный в функцию обратного вызова, см. Пример,

   const gulp = require("gulp")

    gulp.task("message", function(done) {
      console.log("Gulp is running...")
      done()
    });
Мофта
источник
5

Обходной путь: нам нужно вызвать функции обратного вызова (Task и Anonymous):

function electronTask(callbackA)
{
    return gulp.series(myFirstTask, mySeccondTask, (callbackB) =>
    {
        callbackA();
        callbackB();
    })();    
}
Джеки Дэвид Лемос
источник
2

Здесь вы идете: нет синхронных задач .

Нет синхронных задач

Синхронные задачи больше не поддерживаются. Они часто приводили к тонким ошибкам, которые трудно было отладить, например, забывать возвращать потоки из задачи.

Когда вы видите Did you forget to signal async completion?предупреждение, ни один из методов, упомянутых выше, не использовался. Вам нужно будет использовать обратный вызов с ошибкой сначала или вернуть поток, обещание, источник событий, дочерний процесс или наблюдаемый для решения проблемы.

Использование async/await

Если вы не используете ни одну из предыдущих опций, вы можете определить свою задачу как async function, которая обернет вашу задачу в обещание . Это позволяет синхронно работать с обещаниями awaitи использовать другой синхронный код.

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

В принципе, v3.X был проще, но v4.x строг в этих средствах синхронных и асинхронных задач.

Асинхронный / Await довольно простой и удобный способ , чтобы понять рабочий процесс & вопрос.

Используйте этот простой подход

const gulp = require('gulp')

gulp.task('message',async function(){
return console.log('Gulp is running...')
})
Навин Нирбан Ядав
источник
1

Недавно я боролся с этим и нашел правильный способ создать defaultзадачу, которая запускалась sassтогда sass:watch:

gulp.task('default', gulp.series('sass', 'sass:watch'));
Говард М. Льюис Корабль
источник
1

Мое решение: поставить все с асинхронным и ждать глотком.

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

Вам нужно сделать одну вещь:

  • Добавить asyncперед функцией.

const gulp = require('gulp');

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

Чинтани Сугандхика
источник
0

Добавить сделано в качестве параметра в функции по умолчанию. Что будет делать.

bmayur
источник
0

Для тех, кто пытается использовать gulp для локального развертывания, следующий код поможет

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
источник
0

Для меня проблема была в другом: Angular-cli не был установлен (я установил новую версию Node с помощью NVM и просто забыл переустановить Angular Cli)

Вы можете проверить запуск "ng version".

Если у вас его нет, просто запустите "npm install -g @ angular / cli"

Ари Вайсберг
источник