2

I'm following the official docs, but my gulp tasks aren't running in series.

gulp.task("mytask", ["foo", "bar", "baz"]);

gulp.task("foo", function (callback) {
  gulp
    .src("...")
    .pipe(changed("..."))
    .pipe(gulp.dest(function (file) {
      // ...stuff
      return "...";
    }))
    .on("end", function() {
      // ...stuff
      callback();
    });
});

gulp.task("bar", function (callback) {
  //...
});

gulp.task("baz", function (callback) {
  //...
});

But my output looks like this:

Starting 'mytask'...
Starting 'foo'...
Starting 'bar'...                   // <-- foo is not done yet!
Finished 'foo'
Finished 'bar'
Starting 'baz'...
Finished 'baz'
Finished 'mytask'

How do I get them to run in order?

h bob
  • 3,610
  • 3
  • 35
  • 51
  • 1
    You don't. Use `grunt` if you want serial tasks. The whole point of `gulp` is parallel tasks (and streams.) – Evan Davis Dec 16 '14 at 19:06
  • 5
    @Mathletics You are dead wrong. Gulp allows sync and async. There are ways to accomplish both. – h bob Dec 16 '14 at 20:17
  • 1
    possible duplicate of [Gulp. can't figure how to run tasks synchronously after each other](http://stackoverflow.com/questions/22824546/gulp-cant-figure-how-to-run-tasks-synchronously-after-each-other) – Evan Davis Dec 17 '14 at 17:16
  • That "duplicate" answer is not so. My question assumes that the syntax for the parent task handles ordering. Evidently it does not. You need to explicitly restate the order on all dependent tasks, as is shown in the accepted answer below. It is now enough to declare on the parent. – h bob Dec 17 '14 at 21:36

2 Answers2

7

If you want them to run in series you currently have to use the task dependency system, e.g.:

gulp.task("mytask", ["foo", "bar", "baz"]);

gulp.task("foo", function (callback) {
  //...
  callback(...);
});

gulp.task("bar", ['foo'], function (callback) {
  //...
  callback(...);
});

gulp.task("baz", ['bar'], function (callback) {
  //...
  callback(...);
});

It's clunky. I think it's going to be addressed in a future version.

Depending on the situation you could return a promise or event stream instead of passing in and calling a callback.

I suppose I should mention that the run-sequence module is an option as of right now. But the task dependency system illustrated above is the mechanism currently provided by gulp itself. See this comment re: run-sequence and the future of task sequencing in gulp.

JMM
  • 26,019
  • 3
  • 50
  • 55
  • Wow that worked... You're right it's clunky. Do you have a reference where this is documented? – h bob Dec 16 '14 at 20:19
  • And the event stream option doesn't seem to work for me either, but your way does. – h bob Dec 16 '14 at 20:20
  • 1
    Whether you can use the event stream option depends what you're doing in the task. Do you actually have anything happening at `// ...stuff` in your `foo` task? The documentation is pretty confusing, but see the link in my last paragraph and scroll down to "So this example would look like this:". You might also want to take a look at [Support running task synchronously #96](https://github.com/gulpjs/gulp/issues/96). – JMM Dec 16 '14 at 20:28
  • @hbob the text right after the block about returning a promise, starting with "__Note:__" discusses the dependencies (and also maximum concurrency, backing up my point about gulp and how you're using it wrong.) – Evan Davis Dec 16 '14 at 20:44
  • 1
    @Mathletics Maximizing concurrency is great...it doesn't mean you never need things to occur in series. I believe the gulp project has decided to facilitate that in a future version. See [here](https://github.com/gulpjs/gulp/issues/96#issuecomment-46151174) and [changes coming in gulp 4](https://medium.com/@contrahacks/gulp-3828e8126466#68a2). – JMM Dec 16 '14 at 20:53
  • @Mathletics Gulp does both sync and async. There is no concept here of the "right way" or the "wrong way". In my use case I'm using it as a design-time client-side build tool only, and as such I truly don't care about speed. I do care about the validity of results, and to get the results I need, I must do sync operations. – h bob Dec 17 '14 at 14:39
  • @Mathletics sometimes you need to do things in series. Have you ever tried to cook a meal in parallel? You fry the egg AFTER you crack it open. You use an oven AFTER you preheat it. Etc. Don't invite me to your next dinner party. :) – h bob Dec 17 '14 at 14:44
  • 1
    @hbob wrong analogy. You're talking about process; I'm talking about tools. In your analogy, you want to use a pot of boiling water to make a fried egg, but that's the tool to make hard boiled. (It also strikes me that, if you are the expert on sync operations in gulp, you'd be asking a more interesting question than "how do I do sync operations in gulp.") There is a tool for sync operations; it's called Grunt, and it's great for that use case. – Evan Davis Dec 17 '14 at 17:15
  • @Mathletics there's also going to be a tool for it called gulp 4. – JMM Dec 17 '14 at 17:41
  • @Mathletics I'm no expert, that's why I'm here asking questions. I do know however that I prefer gulp to grunt, which has an ugly API. Gulp does what I want, why be a pedant? – h bob Dec 17 '14 at 21:34
3

This answer should be updated to reflect Gulp 4 way of running tasks in a series.

If you want Gulp tasks to run in a series you should use gulp.series to run them, and if you want them to run parallel gulp.parallel.

In using Gulp series you would do something like the following:

gulp.task("mytask", gulp.series(foo, bar, baz));

Those other tasks would probably no longer be tasks but instead consts, like

  const foo = () => {
     return gulp.src("...")
     .pipe(changed("..."))
     .pipe(gulp.dest(function (file) {
      // ...stuff
      return "...";
    }));
  }

hence the reason why the series lists the constants instead of some strings. In moving to Gulp 4 there would probably be other problems arising, but the fixes for a simple gulp file like this one are easy to make.

simple tutorial on gulp 4 https://codeburst.io/switching-to-gulp-4-0-271ae63530c0

user254694
  • 1,461
  • 2
  • 23
  • 46