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.
Did you forget to signal async completion? It is caused because in Gulp 4 all tasks are automatically asynchronous. Synchronous functions execute one after the other, and each function must wait until the previous one is completed before themselves running.
Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don't explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment – it cannot be used in the global scope.
Because await is only valid inside async functions and modules, which themselves are asynchronous and return promises, the await expression never blocks the main thread and only defers execution of code that actually depends on the result, i.e. anything after the await expression.
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:
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.
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])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With