node.js - Hur hanterar man på rätt sätt Gulp's Task-funktion i NodeJS API?


För närvarande känner jag bara till en fungerande metod för att köra Gulp-uppgiften utan gulpfile och 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); } }
);

Det är inte ämnet för frågan; jag förklarade bara vad jag gör och varför min kod är sådan som den är, men om du vet en bättre metod för att köra Gulp-uppgifter utan gulpfile och CLI, vänligen meddela mig.

Nu om ämnet. Fram till nyligen har den sista delen av koden (Gulp.task(TASK_NAME)(/* ... */)) inte avvisats av regeln no-floating-promises i typescript-eslint. Men efter den senaste uppdateringen av @types/gulp (eller typescript-eslint - nu är det svårt att undersöka vilken) varnar typescript-eslint mig:

Löften måste hanteras på lämpligt sätt eller uttryckligen markeras som ignorerade med void-operatorn

där. Jag vet att det inte är ett falskt larm. Ibland bryts mina Gulp-uppgifter med unhandled promise rejection, men det var inte uppenbart var löftet var. Nu hade jag ledtråden, men det är fortfarande oklart.

Jag utforskade det:

  1. Gulp.task() returnerade Undertaker.TaskFunctionWrapped
  2. TaskFunctionWrapped utökar TaskFunctionBase
  3. TaskFunctionBase är (done: TaskCallback): ReturnType<AsyncTask>;
  4. AsyncTask är:
export type AsyncTask<R = any> =
  ((done: VoidCallback) => void)
  | ((done: Callback<R>) => void)
  | (() => ChildProcess | EventEmitter | Observable<R> | PromiseLike<R> | Stream);

Enligt dokumentationen måste task-funktionen returnera ChildProcess, EventEmitter, Observable, Promise eller Stream. Men hur hanterar man det? Gult.task()() är inte thenable:

Felmeddelande:

TS2339: Egenskapen 'catch' finns inte på typen 'void | EventEmitter | ChildProcess | Stream | Observable | PromiseLike'.

Uppdatering: försök @TheBumpaster lösning

Tyvärr säger @typescript/eslint fortfarande till mig "Promises måste hanteras på ett lämpligt sätt eller uttryckligen markeras som ignorerade med void-operatorn" på raden 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); });

Jag höjer medvetet felet i några av gulp-pluginsen. Projektbyggaren når "checkpoint1" men varken "checkpoint2-A" eller "checkpoint2-B". Utmatningen är:

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]:

Kanske indikerar det indirekt att @typescript/eslint:s skrikande inte bara är tomma ord...

Svar #1

Du borde ha varit medveten om att hantering av löften krävs för 'catch'-funktionen.

Enligt 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))

Uppdatering om kommentar:

Kanske kan detta exempel hjälpa dig att visa vad jag menade med min kod ovan.

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)