node.js - ¿Cómo manejar correctamente la función Task de Gulp en la API de NodeJS?
Actualmente, solo conozco un método de trabajo para ejecutar la tarea de Gulp sin gulpfile y CLI:
import Gulp from "gulp";
const TASK_NAME: string = "EXAMPLE_TASK";
Gulp.task(TASK_NAME, Gulp.parallel([
// ... imported task fuctions ...
]);
Gulp.task(TASK_NAME)(
(error?: Error | null): void => { if (isNeitherUndefinedNorNull(error)) { console.error(error); } }
);
No es el tema en cuestión; solo expliqué lo que estoy haciendo y por qué mi código es así, pero si conoces un mejor método para ejecutar una tarea de Gulp sin gulpfile y CLI, por favor avísame.
Ahora sobre el tema. Hasta hace poco, la última parte del código (Gulp.task(TASK_NAME)(/* ... */)) no había sido rechazada por la regla no-floating-promises de typescript-eslint. Pero después de la última actualización de @types/gulp (o typescript-eslint - ahora es difícil investigar cuál) typescript-eslint me advierte:
Las promesas deben manejarse apropiadamente o marcarse explícitamente como ignoradas con el operador
void
Ahí. Sé que no es la falsa alarma. A veces mis tareas de Gulp se rompen en cadena con unhandled promise rejection, pero no era evidente dónde estaba la promesa. Ahora tengo la pista, pero todavía no está claro.
Exploré eso:
Gulp.task()devolvió elUndertaker.TaskFunctionWrappedTaskFunctionWrappedextiende laTaskFunctionBaseTaskFunctionBasees(done: TaskCallback): ReturnType<AsyncTask>;- El
AsyncTaskes:
export type AsyncTask<R = any> =
((done: VoidCallback) => void)
| ((done: Callback<R>) => void)
| (() => ChildProcess | EventEmitter | Observable<R> | PromiseLike<R> | Stream);
Según la documentación, la función de tarea debe devolver el ChildProcess, EventEmitter, Observable, Promise o Stream. Pero, ¿cómo manejarlo? Gult.task()() no es thenable:
Error al enviar mensajes de texto:
TS2339: La propiedad 'catch' no existe en el tipo 'void | EventEmitter | ChildProcess | Stream | Observable | PromiseLike'.
Actualización: prueba la solución de @TheBumpaster
Desafortunadamente, @typescript/eslint todavía me dice "Las promesas deben ser manejadas adecuadamente o marcadas explícitamente como ignoradas con el operador void" en la línea Gulp.task(ProjectBuilder.GULP_TASK_NAME).
const task: Promise<void> = new Promise<void>((resolve: () => void, reject: (error: Error) => void): void => {
console.log("checkpoint1");
Gulp.task(ProjectBuilder.GULP_TASK_NAME)(
(error?: Error | null): void => {
if (isNeitherUndefinedNorNull(error)) {
console.log("checkpoint2-A");
reject(error);
} else {
console.log("checkpoint2-B");
resolve();
}
}
);
});
task.catch((error: Error): void => { console.error(error); });
Intentionalmente genero el error en algunos de los plugins de gulp. El constructor del proyecto llega al "checkpoint1" pero ni a "checkpoint2-A" ni a "checkpoint2-B". La salida es:
D:\XXX\node_modules\async-done\index.js:18
throw err;
^
Error [ERR_UNHANDLED_ERROR]: Unhandled error. ({
uid: 0,
name: '<anonymous>',
branch: false,
error: AssertionError [ERR_ASSERTION]:
Tal vez indica indirectamente que @typescript/eslint gritar no es solo palabra vacía...
Respuesta #1
Deberías haber sido consciente del hecho de que manejar promesas es necesario para la función 'catch'.
Según https://gulpjs.com/docs/en/getting-started/async-completion/
Gulp.Task(ProjectBuilder.GLUP_TASK_NAME)( (error) => { if ( error ) {
throw new Error(error); } // this is already executed
}
const task = new Promise( (resolve, reject ) => {
Gulp.Task(ProjectBuilder.GLUP_TASK_NAME)( (error) => { if ( error ) { reject(error) } resolve() }
});
task().then().catch(e => console.error(e))
Actualización sobre el comentario:
Quizás este ejemplo pueda ayudarte a demostrar lo que he querido decir con mi código anterior.
const gulp = require("gulp")
const taskName = "task-name"
// Example callback
gulp.task(taskName, (error) => {
if (error) {
console.error(error);
}
// It's already executed here
console.log(taskName)
});
// Example Promise object
const Task = new Promise( (resolve, reject) => {
gulp.task(taskName, (error) => {
if (error) {
reject(error)
}
resolve(taskName)
});
});
Task.then(console.log).catch(console.error)
// Example Promise function
const performTask = (_taskName) => {
return new Promise( (resolve, reject) => {
gulp.task(_taskName, (error) => {
if (error) {
reject(error)
}
resolve(_taskName)
});
});
}
performTask(taskName).then(console.log).catch(console.error)
// Example async/await with then/catch
const exampleServiceHandler = async (_taskName) => {
// Perform actions here
try {
return await gulp.task(_taskName) // Resolve the task
} catch (exception) {
return exception;
}
}
exampleServiceHandler(taskName)
.then(console.log)
.catch(console.error)
