Gulp JS — это сборщик проектов и таск-менеджер для фронтенд и веб-разработки, который является достойной альтернативой для популярного Grunt JS. Одной из нескольких вещей, которыми Gulp отличается от Grunt является то, что по умолчанию все задачи запускаются асинхронно. В целом, можно сказать, что все задачи выполняются одновременно.
Недавно, изучая Gulp, я столкнулся с необходимостью синхронного запуска нескольких задач… синхронного. В документации к Gulp упоминается данная проблема, но мне пришлось немного повозиться перед тем, как я с этим разобрался.
Итак, у нас есть 3 способа сделать выполнение задач синхронным, но чтобы это заработало, нужно явно указать зависимости задач. Про зависимости чуть позже, для начала разберем эти 3 способа:
1. Используя обратный вызов, callback
2. Через возвращение потока
3. Воспользоваться Promise
Теперь предположим, что мы имеем еще одну задачу
Главная ошибка, которую я допустил, была в предположении, что если я объявляю в качестве зависимости список задач, то задачи будут выполнены в указанной последовательности, когда выполнение следующей задачи в списке, будет выполняться только после окончания предшествующей задачи. Но это совсем не так:
Для того, чтобы задача
Обратите внимание на то, что каждый раз, когда вы запускаете
Надеюсь, что эта статья кому-то поможет понять, как с помощью Gulp реализовать выполнение своих задач в строго определенном порядке. Но стоит отметить, что именно асинхронный запуск и асинхронное выполнение задач делают Gulp таким быстрым и мощным, поэтому используйте возможность синхронного выполнения только там, где это действительно необходимо.
Недавно, изучая 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 таким быстрым и мощным, поэтому используйте возможность синхронного выполнения только там, где это действительно необходимо.