Как последовательно запускать задачи Gulp один за другим

в этом фрагменте:

gulp.task "coffee", ->
    gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean",->
    gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

В develop задача, которую я хочу запустить clean, и после нее запустите coffee, и когда это будет сделано, запустите что-то еще. Но я не могу понять это. Эта часть не работает. Пожалуйста, порекомендуйте.

Ответ 1

Это еще не официальный релиз, приходящий Gulp 4.0 позволяет легко выполнять синхронные задачи с gulp.series. Вы можете просто сделать это следующим образом:

gulp.task('develop', gulp.series('clean', 'coffee'))

Я нашел хорошее сообщение в блоге о том, как обновить и использовать эти аккуратные функции:  переход на Gulp 4 на примере

Ответ 2

По умолчанию gulp запускает задачи одновременно, если только они не имеют явных зависимостей. Это не очень полезно для таких задач, как clean, где вы не хотите зависеть, но вам нужно, чтобы они запускались раньше всего.

Я написал плагин run-sequence специально, чтобы исправить эту проблему с помощью gulp. После его установки используйте его следующим образом:

var runSequence = require('run-sequence');

gulp.task('develop', function(done) {
    runSequence('clean', 'coffee', function() {
        console.log('Run something else');
        done();
    });
});

Вы можете прочитать полные инструкции на пакете README - он также поддерживает одновременное выполнение некоторых наборов задач.

Обратите внимание, что это будет (эффективно) исправлено в следующей крупной версии gulp, поскольку они полностью устраняют автоматическое упорядочение зависимостей и предоставляют инструменты аналогично run-sequence, чтобы вы могли вручную указать порядок выполнения, как вы хотите.

Однако это серьезное изменение, поэтому нет причин ждать, когда вы можете использовать run-sequence сегодня.

Ответ 3

Единственное хорошее решение этой проблемы можно найти в документации gulp, которую можно найти здесь

var gulp = require('gulp');

// takes in a callback so the engine knows when it'll be done
gulp.task('one', function(cb) {
  // do stuff -- async or otherwise
  cb(err); // if err is not null and not undefined, the orchestration will stop, and 'two' will not run
});

// identifies a dependent task must be complete before this one begins
gulp.task('two', ['one'], function() {
  // task 'one' is done now
});

gulp.task('default', ['one', 'two']);
// alternatively: gulp.task('default', ['two']);

Ответ 4

Я сгенерировал приложение node/gulp, используя generator-gulp-webapp Генератор Yeoman. Он обрабатывал "чистую головоломку" таким образом (перевод на оригинальные задачи, упомянутые в вопросе):

gulp.task('develop', ['clean'], function () {
  gulp.start('coffee');
});

Ответ 5

В соответствии с Gulp документами:

Выполняются ли ваши задачи до завершения зависимостей? Убедитесь, что ваши задачи зависимостей правильно используются подсказками async run: выполните обратный вызов или верните обещание или поток событий.

Синхронизировать последовательность задач:

  • Верните поток событий (например, gulp.src) в gulp.task, чтобы сообщить задача завершения потока.
  • Объявить зависимости задачи во втором аргументе gulp.task.

См. пересмотренный код:

gulp.task "coffee", ->
    return gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean", ['coffee'], ->
      return gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

Ответ 6

run-sequence является наиболее понятным способом (по крайней мере, до тех пор, пока не будет выпущен Gulp 4.0)

С run-sequence ваша задача будет выглядеть так:

var sequence = require('run-sequence');
/* ... */
gulp.task('develop', function (done) {
    sequence('clean', 'coffee', done);
});

Но если вы (по какой-то причине) предпочитаете не использовать его, gulp.start поможет:

gulp.task('develop', ['clean'], function (done) {
    gulp.on('task_stop', function (event) {
        if (event.task === 'coffee') {
            done();
        }
    });
    gulp.start('coffee');
});

Примечание. Если вы только запускаете задачу без прослушивания результата, задача develop заканчивается раньше, чем coffee, и это может запутать.

Вы также можете удалить прослушиватель событий, если это не требуется

gulp.task('develop', ['clean'], function (done) {
    function onFinish(event) {
        if (event.task === 'coffee') {
            gulp.removeListener('task_stop', onFinish);
            done();
        }
    }
    gulp.on('task_stop', onFinish);
    gulp.start('coffee');
});

Рассмотрим также task_err событие, которое вы можете прослушать. task_stop запускается при успешном завершении, а task_err появляется при возникновении некоторой ошибки.

Вы также можете задаться вопросом, почему нет официальной документации для gulp.start(). Этот ответ от члена Gulp объясняет вещи:

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

(источник: https://github.com/gulpjs/gulp/issues/426#issuecomment-41208007)

Ответ 7

У меня была такая же проблема, и решение оказалось для меня довольно легким. В основном измените свой код на следующий, и он должен работать. ПРИМЕЧАНИЕ: возврат до gulp.src сделал для меня все различия.

gulp.task "coffee", ->
    return gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean",->
    return gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

Ответ 8

Я искал этот ответ некоторое время. Теперь я получил его в официальной документации gulp.

Если вы хотите выполнить задачу gulp, когда последняя завершена, вам нужно вернуть поток:

gulp.task('wiredep', ['dev-jade'], function () {
    var stream = gulp.src(paths.output + '*.html')
        .pipe($.wiredep())
        .pipe(gulp.dest(paths.output));

    return stream; // execute next task when this is completed
});

// First will execute and complete wiredep task
gulp.task('prod-jade', ['wiredep'], function() {
    gulp.src(paths.output + '**/*.html')
        .pipe($.minifyHtml())
        .pipe(gulp.dest(paths.output));
});

Ответ 9

Для меня он не запускал задачу minify после конкатенации, поскольку он ожидает конкатенированный ввод и не генерировался несколько раз.

Я попытался добавить к заданию по умолчанию в порядке выполнения, и он не сработал. Он работал после добавления всего return для каждой задачи и получения минимализации внутри gulp.start(), как показано ниже.

/**
* Concatenate JavaScripts
*/
gulp.task('concat-js', function(){
    return gulp.src([
        'js/jquery.js',
        'js/jquery-ui.js',
        'js/bootstrap.js',
        'js/jquery.onepage-scroll.js',
        'js/script.js'])
    .pipe(maps.init())
    .pipe(concat('ux.js'))
    .pipe(maps.write('./'))
    .pipe(gulp.dest('dist/js'));
});

/**
* Minify JavaScript
*/
gulp.task('minify-js', function(){
    return gulp.src('dist/js/ux.js')
    .pipe(uglify())
    .pipe(rename('ux.min.js'))
    .pipe(gulp.dest('dist/js'));
});

gulp.task('concat', ['concat-js'], function(){
   gulp.start('minify-js');
});

gulp.task('default',['concat']); 

Источник http://schickling.me/synchronous-tasks-gulp/

Ответ 10

попробовали все предлагаемые решения, все, похоже, имеют свои проблемы.

Если вы действительно посмотрите на источник Orchestrator, в частности реализацию .start(), вы увидите, что если последний параметр является функцией, он будет рассматривать его как обратный вызов.

Я написал этот фрагмент для своих собственных задач:

  gulp.task( 'task1', () => console.log(a) )
  gulp.task( 'task2', () => console.log(a) )
  gulp.task( 'task3', () => console.log(a) )
  gulp.task( 'task4', () => console.log(a) )
  gulp.task( 'task5', () => console.log(a) )

  function runSequential( tasks ) {
    if( !tasks || tasks.length <= 0 ) return;

    const task = tasks[0];
    gulp.start( task, () => {
        console.log( `${task} finished` );
        runSequential( tasks.slice(1) );
    } );
  }
  gulp.task( "run-all", () => runSequential([ "task1", "task2", "task3", "task4", "task5" ));

Ответ 11

Просто заставьте coffee зависеть от clean, а develop зависит от coffee:

gulp.task('coffee', ['clean'], function(){...});
gulp.task('develop', ['coffee'], function(){...});

Отправка теперь последовательна: cleancoffeedevelop. Обратите внимание, что реализация clean и coffee реализация должны принимать обратный вызов ", поэтому движок знает, когда это будет сделано" :

gulp.task('clean', function(callback){
  del(['dist/*'], callback);
});

В заключение ниже приведен шаблон простой gulp для синхронного clean, за которым следуют асинхронные зависимости сборки:

//build sub-tasks
gulp.task('bar', ['clean'], function(){...});
gulp.task('foo', ['clean'], function(){...});
gulp.task('baz', ['clean'], function(){...});
...

//main build task
gulp.task('build', ['foo', 'baz', 'bar', ...], function(){...})

Gulp достаточно умен, чтобы запустить clean ровно один раз за build, независимо от того, сколько зависимостей build зависит от clean. Как указано выше, clean является барьером синхронизации, тогда все зависимости build выполняются параллельно, затем выполняется build.

Ответ 12

Gulp и Node используйте promises.

Итак, вы можете сделать это:

// ... require gulp, del, etc

function cleanTask() {
  return del('./dist/');
}

function bundleVendorsTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

function bundleAppTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

function tarTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

gulp.task('deploy', function deployTask() {
  // 1. Run the clean task
  cleanTask().then(function () {
    // 2. Clean is complete. Now run two tasks in parallel
    Promise.all([
      bundleVendorsTask(),
      bundleAppTask()
    ]).then(function () {
      // 3. Two tasks are complete, now run the final task.
      tarTask();
    });
  });
});

Если вы вернете поток gulp, вы можете использовать метод then() для добавления обратного вызова. В качестве альтернативы вы можете использовать Node native Promise, чтобы создать свой собственный promises. Здесь я использую Promise.all(), чтобы иметь один обратный вызов, который срабатывает, когда разрешается все promises.

Ответ 13

Попробуй этот хак:-) Gulp v3.x Hack для ошибки Async

Я пробовал все "официальные" способы в Readme, они не работали для меня, но это было сделано. Вы также можете перейти на gulp 4.x, но я настоятельно рекомендую вам этого не делать, это ломает так много всего. Вы могли бы использовать реальное обещание js, но эй, это быстро, грязно, просто:-) По существу вы используете:

var wait = 0; // flag to signal thread that task is done
if(wait == 0) setTimeout(... // sleep and let nodejs schedule other threads

Отправляй сообщение!