Выполнение задач в серии, которая динамически создает файл в Gulp 4

Недавно я перешел с использования Gulp 3 на Gulp 4. Представляем новые задачи, такие как gulp.src() а также gulp.parallel() добавляет больше гибкости и простоты использования.
Вот мой код, пытающийся выполнять задачи последовательно.

  1. Асинхронная задача, которая создает файлы динамически

    let css_purge_libs = async () => {
    var pacs = ["!bootstrap", "bulma", "animate.css"];
    var paths = await fetch_resources(pacs, "bower", "css|sass");
    возврат gulp.src (пути)
      .pipe(before(true, config.css.destination.temp + "/lib")())
      .pipe(P.if(/\.sass$/ г, P.sass().on('ошибка', P.sass.logError)))
      .pipe(P.purgecss(config.css.purgecss))
      .pipe(gulp.dest(config.css.destination.temp + "/lib"));
    };

написал код выше, чтобы получить .css or .sass файлы из конкретных пакетов Bower, о которых не упоминалось main недвижимость в bower.json(не нужен дополнительный плагин, как wiredep). файлы будут созданы на лету в temp папка.

  1. Построение, создание конкатов и исходных карт

    let css_build = () => {
    let paths = [`${config.css.destination.temp}/**/*.css`, `${config.css.destination.dev}**/*.css`];
    возврат gulp.src (пути)
      .pipe(before(true, config.css.destination.build)())
      .pipe(P.postcss(config.css.postcss.plugins))
      .pipe(P.if(prod, P.sourcemaps.init()))
      .pipe(P.if(prod, P.cssnano()))
      .pipe(P.if(prod, P.concat("ariyana-build.css")))
      .pipe(P.if(prod, P.rev()))
      .pipe(P.if(prod, P.sourcemaps.write(".")))
      .pipe(gulp.dest(config.css.destination.build));
    }

извлеченные ресурсы и ресурсы проекта будут отправлены через поток для обработки.

  1. Определения задач Gulp

    gulp.task('css:purge-libs', css_purge_libs); 
    gulp.task('css:build', css_build);
    gulp.task("serve:dev", gulp.series(css_purge_libs, css_build, serve_dev));

    Сценарий проблемы

Когда я выпускаю gulp serve:dev, что происходит, прикреплено в журналах ниже.

[00:19:19] Using gulpfile D:\Enterprise\test\gulpfile.js
[00:19:19] Starting 'serve:dev'...
[00:19:19] Starting 'css_purge_libs'...
[00:19:21] Finished 'css_purge_libs' after 1.86 s
[00:19:21] Starting 'css_build'...
[00:19:25] bower_components\bulma\bulma.sass
[00:19:25] app\styles\bootstrap-reboot.css
[00:19:25] bower_components\animate.css\animate.css
[00:19:26] app\styles\main.css
[00:19:26] Finished 'css_build' after 4.69 s
[00:19:26] Starting 'serve_dev'...
[00:19:26] Finished 'serve_dev' after 1.57 ms
[00:19:26] Finished 'serve:dev' after 6.57 s

похоже глоток не поднял динамически созданные файлы в .tmp/styles/lib Ресурсы CSS. Я мог бы подумать причину, что происходит, потому что операция ввода-вывода происходит под капотом, может быть асинхронной операцией, так что gulp не имеет ни малейшего понятия, выполнена ли операция

Сценарий ответа

let sloop = ()=> {
  return new Promise(resolve=> {
    setTimeout(resolve, 2000);
  });
}

когда я добавляю немного твика, который приносит задержку и вводится в определение задачи

gulp.task('css:purge-libs', css_purge_libs); 
gulp.task('css:build', css_build);
gulp.task("serve:dev", gulp.series(css_purge_libs, sloop, css_build, serve_dev));

это пришло как выходной журнал, который я ожидал.

[00:28:58] Using gulpfile D:\Enterprise\test\gulpfile.js
[00:28:58] Starting 'serve:dev'...
[00:28:58] Starting 'css_purge_libs'...
[00:29:00] Finished 'css_purge_libs' after 1.8 s
[00:29:00] Starting 'sloop'...
[00:29:00] bower_components\bulma\bulma.sass
[00:29:00] bower_components\animate.css\animate.css
[00:29:02] Finished 'sloop' after 2.18 s
[00:29:02] Starting 'css_build'...
[00:29:08] .tmp\styles\lib\animate.css
[00:29:08] .tmp\styles\lib\bulma.css
[00:29:08] app\styles\bootstrap-reboot.css
[00:29:08] app\styles\main.css
[00:29:08] Finished 'css_build' after 6.43 s
[00:29:08] Starting 'serve_dev'...
[00:29:08] Finished 'serve_dev' after 2.96 ms
[00:29:08] Finished 'serve:dev' after 10 s

введение новой задержки между асинхронными операциями решило мою проблему

Вопросы

  1. Почему это происходит?(Пожалуйста, дайте мне подробное объяснение, потому что я ищу внутренности)
  2. Почему Gulp Stream не может опрашивать, если файл был создан или нет.
  3. Есть ли лучший способ справиться с такими сценариями?

1 ответ

Решение

К сожалению, это известная проблема в gulp, которая не имеет обходного пути: https://github.com/gulpjs/gulp/issues/1421

То, что вы возвращаете из своей задачи, говорит gulp, как ждать: вы можете вернуть Stream (gulp ждет его завершения) или Promise (gulp ждет его разрешения) и т. Д. Что вы не можете сделать, так как пытаетесь сделать, это вернуть обещание для потока.

Решение, на данный момент, заключается в том, чтобы вручную дождаться окончания потока gulp внутри вашей асинхронной функции, например, так:

let myTask = async () => {
    let files = await getFilePaths();
    return new Promise((resolve, reject) => {
        return gulp.src(files)
            .pipe(gulp.dest('someplace'))
            .on('end', resolve)
            .on('error', reject);
    });
};

Это некрасиво, но в настоящее время нет лучшего способа выполнять как стандартные асинхронные вызовы, так и управление потоками в одной задаче.

Другие вопросы по тегам