Синхронная обработка задач в Gulp.JS
Gulp JS это менеджер задач ориентированный на фронтенд-разработку и ближайшая альтернатива Grunt JS.
Одно из нескольких отличий Gulp от Grunt заключается в том, что задачи (по умолчанию) запускаются асинхронно (вау, мне даже в словарь не пришлось заглядывать что бы написать это слово правильно с первого раза!). Приблизительно это означает, что все задачи запускаются одновременно.
Недавно я стал копаться в Gulp и одна из вещей с которыми больше всего пришлось побороться это несколько задач … которые надо было запускать синхронно.
В документации упоминается, как это делать, но после её прочтения несколько вопросов у меня все же оставалось, пока я с ними не разобрался.
Во первых, существуют 3 способа заставить задачу выполняться синхронно, но они должны использоваться вместе с зависимостями задач.
Первый из трех способов:
Передача колбека:
gulp.task('sync', function (cb) {
// setTimeout может быть любой асинхронной задачей
setTimeout(function () {
cb();
}, 1000);
});
Возвращать поток:
gulp.task('sync', function () {
return gulp.src('js/*.js')
.pipe(concat('script.min.js')
.pipe(uglify())
.pipe(gulp.dest('../dist/js');
});
Возвращать промис:
gulp.task('sync', function () {
var deferred = Q.defer();
// setTimeout может быть любой асинхронной задачей
setTimeout(function () {
deferred.resolve();
}, 1000);
return deferred.promise;
});
Допустим, у нас есть задача, которая требует выполнения созданной нами выше задачи sync
(подойдет любая из трех).
Недостаточно просто объявить задачу sync
, как мы это сделали, нужно указать её в
качестве зависимости другой задачи:
gulp.task('secondTask', ['sync'], function () {
// эта задача не запустится пока
// задача sync не закончит работу!
});
В чем я ошибся, так это в том, что думал, что если я указываю несколько зависимостей они будут выполняться последовательно. Следующий код так НЕ РАБОТАЕТ:
gulp.task('thirdTask', function () {
// обратите внимание, что у задачи нет зависимостей
});
// Я надеялся, что запустится задача sync,
// ЗАТЕМ задача thirdTask и ЗАТЕМ — default,
// но ЭТО НЕ ТАК. Этот код запустит ОДНОВРЕМЕННО
// sync И thirdTask и затем — default.
gulp.task('default', ['sync', 'thirdTask'], function () {
// делаем всякое
});
Что бы запускать default так, как я хотел, нужно было, кроме всего прочего, объявить sync
зависимостью thirdTask
:
gulp.task('thirdTask', ['sync'] function () {
// теперь задача основана на sync. Если она
// возвращает поток, то default не запустится
// до тех пор, пока не закончит работу thirdTask
});
gulp.task('default', ['sync', 'thirdTask'], function () {
// делаем всякое
});
Обратите внимание на то, что будет происходить, если у вас есть задача watch
, которая
запускает thirdTask
. Каждый раз, когда вы запускаете thirdTask
, будет также
запускаться sync
, что может быть нежелательным!
В любом случае, надеюсь эта статья сможет помочь тем, кто пытается разобраться как запускать задачи в определенном порядке. И обратите внимание на то, что одна из вещей, которая делает Gulp быстрым и мощным это возможность запускать множество задач одновременно, так что запускайте их синхронно только тогда, когда это действительно нужно