Node libraries handle asynchronicity in a variety of ways. The most common pattern is error-first callbacks, but you might also encounter streams, promises, event emitters, child processes, or observables. Gulp tasks normalize all these types of asynchronicity.
Signal task completion
When a stream, promise, event emitter, child process, or observable is returned from a task, the success or error informs gulp whether to continue or end. If a task errors, gulp will end immediately and show that error.
When composing tasks with
series(), an error will end the composition and no further tasks will be executed. When composing tasks with
parallel(), an error will end the composition but the other parallel tasks may or may not complete.
Returning a stream
Returning a promise
Returning an event emitter
Returning a child process
Returning an observable
Using an error-first callback
If nothing is returned from your task, you must use the error-first callback to signal completion. The callback will be passed to your task as the only argument - named
cb() in the examples below.
To indicate to gulp that an error occurred in a task using an error-first callback, call it with an
Error as the only argument.
However, you'll often pass this callback to another API instead of calling it yourself.
No synchronous tasks
Synchronous tasks are no longer supported. They often led to subtle mistakes that were hard to debug, like forgetting to return your streams from a task.
When you see the "Did you forget to signal async completion?" warning, none of the techniques mentioned above were used. You'll need to use the error-first callback or return a stream, promise, event emitter, child process, or observable to resolve the issue.
When not using any of the previous options, you can define your task as an
async function, which wraps your task in a promise. This allows you to work with promises synchronously using
await and use other synchronous code.