I'm trying to make a function which calls some other functions :
copy = () => {
copyHtml();
copyCss();
copyJs();
copyImg();
}
exports.copy = copy;
Using gulp copy
, the function works but I get this error :
The following tasks did not complete: copy. Did you forget to signal async completion?
I'm not used to it and after searching I just changed my function like below, it works without error :
copy = (done) => {
copyHtml();
copyCss();
copyJs();
copyImg();
done();
}
exports.copy = copy;
Then I added it to my default function :
defaultFunction = () => {
copy();
browsersyncServe();
}
exports.default = defaultFunction;
My problem is when I call the default function with gulp :
done is not a function
If I directly call copyHtml
, copyCss
, copyJs
and copyImg
in the default function, it works and I get no error.
What am I missing ?
It appears that your functions run synchronously, without returning anything. While this works in early versions of gulp, currently it no longer supports synchronous functions. Now you need to use a callback (like in your question), or return a stream, promise, event emitter, child process, or observable (see https://stackoverflow.com/a/36899424 for some implementations).
For your case, there are a bunch of things that could work, but here are three possibilities:
async
FunctionsBecause gulp supports promises, you can just make all of your functions async. You can call these functions like synchronous functions (since they are really synchronous under the hood):
copy = async () => {
copyHtml();
copyCss();
copyJs();
copyImg();
}
defaultFunction = async () => {
// the await isn't strictly necessary, since copy is actually
// synchronous, but it's probably good practice to use await,
// if copy ever becomes asynchronous
await copy();
browsersyncServe();
}
exports.copy = copy;
exports.default = defaultFunction;
In the same vein, you can return a resolved promise (like Promise.resolve()
) for any synchronous function gulp uses. Like the above example, this doesn't interfere with the synchronous invocation of these functions (as long as the returned value is ignored):
copy = () => {
copyHtml();
copyCss();
copyJs();
copyImg();
return Promise.resolve();
}
defaultFunction = () => {
copy();
browsersyncServe();
return Promise.resolve();
}
exports.copy = copy;
exports.default = defaultFunction;
Another possibility is to wrap your synchronous functions to become asynchronous. For example, using the asynchronous callback format would look something like this:
function wrapSyncToAsync(fn) {
return function (done) {
fn();
done();
};
}
copy = () => {
copyHtml();
copyCss();
copyJs();
copyImg();
}
defaultFunction = () => {
copy();
browsersyncServe();
}
exports.copy = wrapSyncToAsync(copy);
exports.default = wrapSyncToAsync(defaultFunction);
Here copy
is your synchronous version that you can call via just copy()
, while exports.copy
is what gulp will call with a callback, e.g. exports.copy(callbackFunction)
.
You can use wrapSyncToAsync
to convert synchronous functions (that don't have any arguments) to asynchronous functions.