15 October 2014

Последовательное выполнение задач в Gulp JS

Website developmentJavaScriptNode.JS
Original author: Cameron Spear
Gulp JS — это сборщик проектов и таск-менеджер для фронтенд и веб-разработки, который является достойной альтернативой для популярного Grunt JS. Одной из нескольких вещей, которыми Gulp отличается от Grunt является то, что по умолчанию все задачи запускаются асинхронно. В целом, можно сказать, что все задачи выполняются одновременно.

Недавно, изучая Gulp, я столкнулся с необходимостью синхронного запуска нескольких задач… синхронного. В документации к Gulp упоминается данная проблема, но мне пришлось немного повозиться перед тем, как я с этим разобрался.

Итак, у нас есть 3 способа сделать выполнение задач синхронным, но чтобы это заработало, нужно явно указать зависимости задач. Про зависимости чуть позже, для начала разберем эти 3 способа:

1. Используя обратный вызов, callback
gulp.task('sync', function (cb) {  
    // setTimeout может быть асинхронной задачей
    setTimeout(function () {
        cb();
    }, 1000);
});


2. Через возвращение потока
gulp.task('sync', function () {  
    return gulp.src('js/*.js')
        .pipe(concat('script.min.js')
        .pipe(uglify())
        .pipe(gulp.dest('../dist/js');
});


3. Воспользоваться Promise
gulp.task('sync', function () {  
    var deferred = Q.defer();
    // setTimeout может быть асинхронной задачей
    setTimeout(function () {
        deferred.resolve();
    }, 1000);
    return deferred.promise;
});


Теперь предположим, что мы имеем еще одну задачу secondTask, которая зависит от результатов выполнения задачи sync (которую мы создали одним из способов описанных выше). Поэтому мы объявляем нашу задачу sync как зависимость для задачи secondTask:

gulp.task('secondTask', ['sync'], function () {  
    // эта задача не буде запущена пока
    // задача 'sync' не закончит работу!
});


Главная ошибка, которую я допустил, была в предположении, что если я объявляю в качестве зависимости список задач, то задачи будут выполнены в указанной последовательности, когда выполнение следующей задачи в списке, будет выполняться только после окончания предшествующей задачи. Но это совсем не так:

gulp.task('thirdTask', function () {  
    // эта задача не зависит от других
});

// Я надеялся, что этот код сначала запустит
// задачу 'sync', затем будет запущена
// задача 'thridTask' и только потом будет
// выполнена задача 'default'. Но это не так.
// Перед выполнении задачи 'default', задачи
// 'sync' и 'thridTask будут запущены
// ОДНОВРЕМЕННО
gulp.task('default', ['sync', 'thirdTask'], function () {  
    // что-то делаем
});


Для того, чтобы задача default была выполнена в той последовательности как я хотел, задачу thirdTask необходимо сделать зависимой от задачи sync.

gulp.task('thirdTask', ['sync'] function () {  
    // теперь эта задача зависит от 'sync'. Если здесь
    // будет возвращен поток, то задача 'default' не будет
    // запущена, пока 'thirdTask' не будет закончена
});

gulp.task('default', ['sync', 'thirdTask'], function () {  
    // что-то делаем
});


Обратите внимание на то, что каждый раз, когда вы запускаете thirdTask, будет также запускаться sync. Это может быть нежелательным поведением, если у вас есть некоторая задача watch, которая запускает задачу thirdTask.

Надеюсь, что эта статья кому-то поможет понять, как с помощью Gulp реализовать выполнение своих задач в строго определенном порядке. Но стоит отметить, что именно асинхронный запуск и асинхронное выполнение задач делают Gulp таким быстрым и мощным, поэтому используйте возможность синхронного выполнения только там, где это действительно необходимо.
Tags:gulpjavascriptnodejs
Hubs: Website development JavaScript Node.JS
+3
17.8k 69
Comments 11
Top of the last 24 hours