How to use async/await with Gulp 4?
Asked Answered
S

2

18

I'm trying to do something like this:

gulp.task("test", async () => {
    return gulp.src("**/*.scss")
        .pipe(print((filePath) => `File: ${filePath}`));
});

(print is gulp-print)

But it gives the following:

[22:08:43] Starting 'test'...
[22:08:43] Finished 'test' after 12 ms
[22:08:43] File: src\app\styles\app.scss
[22:08:43] File: src\app\styles\test.scss

i.e. It finishes before the messages are printed.

I'm using Gulp 4 (alpha 2 I think) and TypeScript (1.8.0-dev.20151204).

The generated (ES6) code looks like this:

gulp.task("test", () => __awaiter(this, void 0, Promise, function* () {
    return gulp.src("**/*.scss")
        .pipe(print((filePath) => `File: ${filePath}`));
}));

Where __awaiter is:

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
    return new Promise(function (resolve, reject) {
        generator = generator.call(thisArg, _arguments);
        function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
        function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
        function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
        function step(verb, value) {
            var result = generator[verb](value);
            result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject);
        }
        step("next", void 0);
    });
};

Is it possible to get this working? I want to use await within my task function, but I can't do this without marking the function as asynchronous.

I'm probably missing something obvious.

Swayback answered 9/12, 2015 at 20:24 Comment(0)
S
24

I was able to get this working with help from here and here.

gulp.task("test", async () => {
    await new Promise((resolve, reject) => {
        gulp.src("**/*.scss")
            .pipe(print((filePath) => `File: ${filePath}`))
            .on("end", resolve);
    });
});

In my real task, I had to use the finish event instead of the end event (see the 2nd link above).

It's not crystal-clear how this all works, but I think it's something along the lines of:

  1. Gulp functions are async, so they need to be awaited, but since they aren't promises, you have to wrap them in one.
  2. In order to resolve the promise, you need to listen to either the end or the finish event, and which one depends on what the last pipe returns.

Another option that appears to work is resume() followed by on("end"), in cases where finish is usually needed. This is probably because of this. I'm not sure which option is better.

I would love to understand this more, so if you're able to explain this in simple terms, please feel free to comment or post an answer.

Edit: You can also return the promise, instead of awaiting it.

Swayback answered 10/12, 2015 at 10:6 Comment(1)
As of gulp 4 in 2023, Gulp is still not using native promises. Very annoying,Barry
O
5

Based on @glen-84 answer i've found my solution, it's not really different, but it's also not the same.

Somehow with the correct answer for Tasks I've got some problems when using parallel/series directly, leading again to the did you signal async completion error. Could be caused by an error i've overseen in my code.

Based on this example in the undertaker readme:

taker.task('task3', function(){
  return new Promise(function(resolve, reject){
    // do things

    resolve(); // when everything is done
  });
});

I've used this structure, which seems to work fine for task and series/parallel:

function someTask() {
    return new Promise(async (resolve, reject) => {
        await prepareSomethingAsync()
        gulp.src(somePath)
            .pipe(doingSomething())
            .pipe(await doingSomethingBasedOnAsyncResult())
            .on('finish', resolve)
            .on('error', reject)
    })
}

// e.g.: gulp.task('Some Name', someTask)

// e.g.: gulp.series(someTask)

// e.g.: gulp.parallel([someTask, someTask])
Oren answered 12/9, 2021 at 23:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.