1

我最近从使用 Gulp 3 迁移到 Gulp 4。引入了新的任务,例如gulp.src()gulp.parallel()增加了更多的灵活性和易用性。
这是我尝试连续执行任务的代码。

  1. 动态创建文件的异步任务

    让 css_purge_libs = async () => {
    var pacs = ["!bootstrap", "bulma", "animate.css"];
    var paths = await fetch_resources(pacs, "bower", "css|sass");
    返回 gulp.src(路径)
      .pipe(之前(true, config.css.destination.temp + "/lib")())
      .pipe(P.if(/\.sass$/gm, P.sass().on('error', 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. 构建、连接和源图生成

    让 css_build = () => {
    让路径 = [`${config.css.destination.temp}/**/*.css`, `${config.css.destination.dev}**/*.css`];
    返回 gulp.src(路径)
      .pipe(之前(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

看起来 gulp 没有在.tmp/styles/libcss 资源中获取动态创建的文件。我可以想到一个原因,因为 IO 操作发生在幕后可能是异步操作,所以 gulp 不知道操作是否完成

答案场景

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

当我添加一点 tweek 会带来延迟并在任务定义中引入

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 流无法轮询文件是否已完成创建。
  3. 有没有更好的方法来处理这些场景?
4

1 回答 1

2

不幸的是,这是 gulp 中的一个已知问题,没有解决方法:https ://github.com/gulpjs/gulp/issues/1421

你从任务中返回的内容告诉 gulp 如何等待:你可以返回一个 Stream(gulp 等待它完成)或一个 Promise(gulp 等待它解决)等等。你不能做什么,因为你正在尝试做,是为 Stream 返回一个 Promise

目前,解决方案是手动等待 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);
    });
};

这很难看,但目前没有更好的方法可以在单个任务中同时执行标准异步调用和流管理。

于 2018-12-26T21:20:02.317 回答