0

在下面的代码中,fileShouldBePreprocessedBySass()将在console.log('intercepted!');执行前调用。此外,在 中fileShouldBePreprocessedBySass(targetFileAbsolutePath),参数targetFileAbsolutePath将是undefined

let currentSourceFileAbsolutePath;

return gulp.src(entryPointsSourceFilesPathsOrGlobs)

    // "gulpPlugins.intercept" is "gulp-intercept"
    .pipe(gulpPlugins.intercept( sourceVynilFile => {
      console.log('intercepted!');
      currentSourceFileAbsolutePath = sourceVynilFile.path;
      console.log(currentSourceFileAbsolutePath); // OK here
      return sourceVynilFile;
    }))

    // "gulpPlugins.if" is "gulp-if"
    .pipe(gulpPlugins.if(
        // currentSourceFileAbsolutePath is undefined !!!
        fileShouldBePreprocessedBySass(currentSourceFileAbsolutePath),
        gulpPlugins.sass()
    ));

// ...

fileShouldBePreprocessedBySass(targetFileAbsolutePath) {

    console.warn('---');
    console.warn(targetFileAbsolutePath); // undefined!

    const targetFilenameExtension = Path.extname(targetFileAbsolutePath);
    let targetFilenameExtensionIsSupportedBySassPreprocessor = false;

    for (const filenameExtension of SUPPORTED_FILENAME_EXTENSIONS__SASS_PREPROCESSOR) {
      if (filenameExtension === targetFilenameExtension) {
        targetFilenameExtensionIsSupportedBySassPreprocessor = true;
        break;
      }
    }

    return targetFilenameExtensionIsSupportedBySassPreprocessor;
}

真的,原始代码是用 TypeScript 编写的,但我将其重写为 JavaScript 以让更多人理解代码。我之所以这么说是因为 TypeScript 编译器以某种方式理解,pipe(gulpPlugins.if(/*...*/))参数currentSourceFileAbsolutePath没有初始化,所以发生了TS2454: Variable 'currentSourceFileAbsolutePath' is used before being assigned.错误。

我很困惑,因为我有类似的任务可以正常工作(按正确的顺序):

let currentSourceFileAbsolutePath: string;

return gulp.src(entryPointsSourceFilesPathsOrGlobs)

    .pipe(gulpPlugins.intercept(sourceVynilFile => {
      currentSourceFileAbsolutePath = sourceVynilFile.path;
      return sourceFile;
    }))

    .pipe(gulpPlugins.pug())
    .pipe(gulpPlugins.intercept(compiledHtmlFile => {
      // currentSourceFileAbsolutePath is NOT undefined!
      if (shouldValidateCompiledHtmlRespectiveToSourceFile(currentSourceFileAbsolutePath)) {
        HtmlValidator.validateHtml(compiledHtmlFile);
      }
      return compiledHtmlFile;
    }))

    .pipe(gulp.dest(() => (
      // currentSourceFileAbsolutePath is NOT undefined!
      getOutputDirectoryForPreprocessedMarkupEntryPointFileByRespectiveSourceFile(currentSourceFileAbsolutePath)
    )));

第一个任务有什么问题?我错过了一些异步呼叫?

4

1 回答 1

1

Gulp 本身不会对后续调用.pipe. 我不确定你的情况到底发生了什么,但你的代码不必要地脆弱

考虑这种模式:

gulp.src("...")
  .pipe(pluginA)
  .pipe(pluginB)

并假设pluginA只打印到控制台pluginApluginB打印到控制台pluginB。您可能认为输出将是:

pluginA
pluginB
pluginA
pluginB
pluginA
...

换句话说,每个文件都会经过pluginA,然后这个文件会经过pluginB,然后下一个文件会经过pluginA,依此类推。也就是说,直到处理完前一个已完成处理的文件,pluginA才会看到新文件。尽管在某些情况下,这个顺序正是将要发生的事情,但对于一般情况,这个顺序并不能保证。你也可以拥有:pluginBpluginA

pluginA 
pluginA 
pluginA 
pluginB 
pluginA 
pluginB 
pluginB 
pluginB
pluginA 
...

这些文件必须首先看到pluginA,但不能保证会在获取下pluginB一个文件之前处理文件。pluginA

如果处理顺序恰好像我上面给出的第一个示例那样完美交错,则您的代码可以正常工作。但一般来说,这个顺序是不能保证的,你的代码会失败。

碰巧你的代码的脆弱部分是不必要的。不必将文件的路径记录在文件流外部的变量中,然后在流的后面部分读取它。gulp-if会将它测试的文件传递给你给它的条件。这是一个例子:

const gulp = require("gulp");
const gulpIf = require("gulp-if");
gulp.task("default", () =>
          gulp.src("src/**")
          .pipe(gulpIf((file) => {
            console.log(file.path);
            return file.basename === "a";
          }, gulp.dest("out"))));

此任务会将out所有基本名称为"a". 您还将在控制台上看到通过给定条件的每个文件的绝对路径gulpIf

您可以修改fileShouldBePreprocessedBySass以接受 Vinyl 文件,然后只检查file.path那里而不是保存它然后检索它。

于 2019-03-30T12:23:38.867 回答