【问题标题】:How to handle properly the Gulp's Task function in NodeJS API?如何在 NodeJS API 中正确处理 Gulp 的 Task 函数?
【发布时间】:2021-05-16 02:14:56
【问题描述】:

目前,我只知道一种在没有 gulpfile 和 CLI 的情况下运行 Gulp 任务的工作方法:

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); } }
);

这不是问题的主题;我只是解释了我在做什么以及为什么我的代码是这样的,但是如果你知道 没有gulpfile 和 CLI 的 Gulp 任务执行的更好方法,现在请告诉我。

现在关于主题。直到最近,代码的最后一部分(Gulp.task(TASK_NAME)(/* ... */)) 如果typescript-eslint,则未被no-floating-promises 规则拒绝。通过@types/gulp 的最新更新(或typescript-eslint - 现在很难探索哪一个) typescript-eslint警告我:

必须正确处理承诺或使用void 运算符明确标记为忽略

那里。我知道这不是虚惊一场。有时我的 Gulp 任务链因unhandled promise rejection 而中断,但承诺在哪里并不明显。现在我有了提示,但仍然不清楚。

我对此进行了探索:

  1. Gulp.task() 返回了 Undertaker.TaskFunctionWrapped
  2. TaskFunctionWrapped 扩展了 TaskFunctionBase
  3. TaskFunctionBase(done: TaskCallback): ReturnType<AsyncTask>;
  4. AsyncTask 是:
export type AsyncTask<R = any> =
  ((done: VoidCallback) => void)
  | ((done: Callback<R>) => void)
  | (() => ChildProcess | EventEmitter | Observable<R> | PromiseLike<R> | Stream);

根据documentation,任务函数必须返回ChildProcessEventEmitterObservablePromiseStream。但是如何处理呢? Gult.task()() 不可用:

发短信错误:

TS2339:类型“void |”上不存在属性“catch”事件发射器 |子进程 |流 |可观察 | PromiseLike'。

更新:@TheBumpaster 解决方案尝试

不幸的是,@typescript/eslint 仍然在Gulp.task(ProjectBuilder.GULP_TASK_NAME) 行中告诉我“必须正确处理承诺或使用void 运算符明确标记为忽略”。

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); });

我故意在一些 gulp 插件中增加错误。项目构建器到达"checkpoint1",但既没有到达"checkpoint2-A",也没有到达"checkpoint2-B"。输出是:


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

也许它间接表明@typescript/eslint 大喊大叫不是口头上的......

【问题讨论】:

    标签: node.js typescript promise gulp typescript-eslint


    【解决方案1】:

    您应该已经知道“catch”函数需要处理承诺。

    根据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))
    

    评论更新:

    也许这个例子可以帮助你证明我上面的代码是什么意思。

    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)
    

    【讨论】:

    • 感谢您的回答。抱歉检查得太晚了。恐怕,task() 在您的代码中是不可调用的。你的意思是返回Gulp.Task(ProjectBuilder.GLUP_TASK_NAME)(..)?如果是这样,则必须没有 {}
    • Gulp 是一个命名空间,Task 是一个类函数。您所指的 {} 来自回调函数块。也许您期望 Gulp.Task 处理一个承诺,但这不会发生,您需要用 Promise() 包装它或使用 gulp-promise 库
    • 感谢您在获得声誉奖后对您的解决方案的支持。不幸的是,@typescript-eslint 仍然不喜欢这个解决方案。此外,我做了一些实验,知道发生错误时我们没有到达if (error) { reject() } 。如果你愿意,你可以检查更新的问题吗?此外,您注释为“示例 Promise 对象”的示例与不区分大小写有很大不同。例如,我们有gulp.task(taskName, (error) =&gt; {}),但我们的案例是gulp.task(taskName)((error) =&gt; {})(没有gulpfile 的gulp 应用程序的无证执行)。
    猜你喜欢
    • 2020-09-24
    • 2018-09-02
    • 2019-11-24
    • 2019-03-09
    • 2021-06-16
    • 2017-09-25
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多