Node.js & Gulp: Реальная последовательность трубопроводов может отличаться от написанной цепочки .pipe ()? - PullRequest
0 голосов
/ 28 марта 2019

В приведенном ниже коде 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)
    )));

Что не так в первом задании? Я пропустил какой-то асинхронный вызов?

1 Ответ

1 голос
/ 30 марта 2019

Gulp, само по себе, не переупорядочивает то, что происходит при последующих вызовах к .pipe.Я не уверен, что именно происходит в вашем случае, но ваш код излишне хрупок .

Рассмотрим этот шаблон:

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

И предположим, что pluginA просто печатает на консоль pluginA и pluginB просто печатает на консоль pluginB.Вы можете подумать, что вывод будет:

pluginA
pluginB
pluginA
pluginB
pluginA
...

Другими словами, каждый файл будет проходить через pluginA, а затем этот файл будет проходить через pluginB, затем следующий файл будет проходить через pluginA и т. д. То есть pluginA не увидит новый файл, пока pluginB не обработает предыдущий файл, который pluginA завершил обработку.Хотя бывают случаи, когда этот порядок является именно тем, что произойдет, для общего случая этот порядок не гарантируется .Вы также можете иметь:

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 так, чтобы он принимал файл винила, и просто отметьте file.path вместо сохранения и последующего извлечения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...