Помилка Gulp: Наступні завдання не виконані: Ви забули подати сигнал про завершення асинхронізації?


211

У мене є такий 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

Відповіді:


448

Оскільки ваше завдання може містити асинхронний код, ви повинні сигналізувати прогалину, коли ваше завдання закінчиться виконанням (= "завершення асинхронізації").

У Gulp 3.x ви могли піти, не роблячи цього. Якщо ви явно не сигналізували про завершення асинхронного завершення, просто припустимо, що ваше завдання є синхронічним і що воно завершено, як тільки ваша функція завдання повернеться. Gulp 4.x в цьому плані суворіший. Ви повинні чітко сигналізувати про виконання завдання.

Це можна зробити шістьма способами :

1. Поверніть потік

Це насправді не варіант, якщо ви лише намагаєтеся надрукувати щось, але це, мабуть, найбільш часто використовуваний механізм завершення асинхронізації, оскільки ви зазвичай працюєте з потоками глоток. Ось (досить надуманий) приклад, що демонструє це для вашого випадку використання:

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 / wait, це може бути спрощено ще більше. Усі функції, позначені asyncнеявно, повертають Обіцяння, тож працює і наступне (якщо ваша версія 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
Через пару годин гуглінгу я знайшов цей приклад. Дуже корисний. Дякую!
paxtor

це мені корисно, ти!
Анан

1
Я дуже ціную вашу відповідь. +1 великий час.
Конрад Вільтерстен

6
Я високо оцінив вашу вишукану та інформативну відповідь 17 листопада. І сьогодні, в день Різдва, я знову ціную це заново. Це один із випадків, коли я хочу, щоб я міг нагородити +2 ... Я не можу повірити, що goolearching не виводить це посилання як перше місце під час пошуку " Наступні завдання не виконані " або " Чи ти забули подати сигнал про завершення асинхронізації? "...
Конрад Вільтерстен

"часто використовуваний пакет del повертає обіцянку". Я використовую del, як я можу написати свій ковток, щоб скористатися обіцянкою? (PS. Абсолютно дивовижна відповідь! +1)
Даніель Тонон

84

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

Для вирішення цієї проблеми спробуйте змінити свій поточний код:

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

наприклад у цьому:

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

або до цього:

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

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

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

Сподіваюсь, це допомагає!


7
Приємно бачити приклад із фактичним змістом завдання
Джонатан

8

Вам потрібно зробити дві речі:

  1. Додати asyncперед функцією.
  2. Почніть свою функцію за допомогою return.

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

7

Я не можу претендувати на те, що я дуже обізнаний з цим питанням, але у мене була така ж проблема і була вирішена.

Існує 7 спосіб вирішити це за допомогою функції асинхронізації .

Напишіть свою функцію, але додайте префікс асинхронізацію .

Роблячи це, Gulp завершує функцію обіцяно, і завдання буде виконуватись без помилок.

Приклад:

async function() {
  // do something
};

Ресурси:

  1. Останній розділ на Ковток сторінці асинхронним Завершення : Використання асинхронної / Await .

  2. Функції асинхронізації Mozilla док .


7

Це проблема під час переходу з gulp версії 3 до 4. Просто ви можете додати параметр, виконаний для функції зворотного дзвінка, див. Приклад,

   const gulp = require("gulp")

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

5

Вирішення: нам потрібно викликати функції зворотного виклику (Завдання та Анонім):

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;

0

Додати виконано як параметр у функції за замовчуванням. Це зробить.


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

0

Для мене проблема була іншою: Angular-cli не був встановлений (я встановив нову версію Node за допомогою NVM і просто забув перевстановити кутовий кліп)

Ви можете перевірити, чи працює "ng версія".

Якщо у вас немає, просто запустіть "npm install -g @ angular / cli"


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.