Return 使用 gulp-tap 将函数结果延迟到下一个 Gulp 管道

Return deferred function result to next Gulp pipe with gulp-tap

我正在创建一个简单的静态站点,在开发过程中,我正在使用 Handlebars.js 并进行一些 API 调用以填充 Handlebars 模板。但是对于生产,我想将所有模板预编译为静态 HTML.

我正在尝试使用 Gulp 使该过程自动化,所以我有一个看起来像这样的任务:

gulp.task('compileHtml', () => {
  return gulp
    .src('index.html')
    .pipe(someThing())
    .pipe(anotherThing())
    .pipe(compileTemplates())
    .pipe(someOtherThing())
    .pipe(gulp.dest('build'));
});

在我的 compileTemplates 函数中,我使用 gulp-tap and jsdom 基本上 运行 包含相关脚本的文件,以进行 API 调用并填写 Handlebars 模板,然后删除那些脚本并将编译后的 HTML 发送回下一个管道。但是我无法推迟发回新的 DOM,直到 jsdom 有足够的时间来 运行 所有脚本。

这是我目前的情况:

const compileTemplates = file => {
  return tap(file => {
    const dom = new JSDOM(file.contents,
      {
        runScripts: 'dangerously',
        resources: 'usable',
        beforeParse(window) {
          window.fetch = require('node-fetch');
        },
      },
    );
    const document = dom.window.document;
    const script = document.querySelector('script[src$="handlebars.min.js"]');

    // dom.serialize() still contains my uncompiled templates at this point
    setTimeout(() => {
      script.remove();
      file.contents = Buffer.from(dom.serialize()); // this is what I want to return from this function
    }, 2500);
  });
};

我知道我可能需要使用承诺在准备就绪后发回 file.contents,但我不擅长承诺或 Gulp。

我尝试返回一个在超时内解决的承诺,但我最终得到 TypeError: dest.on is not a function,因为下一个管道最终期待 file 而不是承诺。

我如何重构以延迟将我操纵的 file 发回下一个管道或从该函数发回一个承诺,然后将该承诺解析为我的新 file compileHtml 任务?

我正在使用 Gulp 4.

参考了,想通了超时后如何解决promise

const compileTemplates = file => {
  return tap(file => {
    const dom = new JSDOM(file.contents,
      {
        runScripts: 'dangerously',
        resources: 'usable',
        beforeParse(window) {
          window.fetch = require('node-fetch');
        },
      },
    );
    const document = dom.window.document;
    const script = document.querySelector('script[src$="handlebars.min.js"]');

    new Promise(resolve => {
      setTimeout(resolve, 2500);
    }).then(() => {
      script.remove();
      file.contents = Buffer.from(dom.serialize());
    });
  });
};

然而,这并没有完全解决我的问题,因为在我的 gulp 任务中,我需要等待承诺得到解决,然后才能将新的 file 发送到下一个管道,但我不能在 gulp-tap.

中找不到任何关于回调的好文档

所以我最终使用了 through2

const compileHtml = file => {
  return through2.obj(function(file, encoding, callback) {
    const dom = new JSDOM(file.contents,
      {
        runScripts: 'dangerously',
        resources: 'usable',
        beforeParse(window) {
          window.fetch = require('node-fetch');
        },
      },
    );
    const document = dom.window.document;
    const script = document.querySelector('script[src$="handlebars.min.js"]');

    new Promise(resolve => {
      setTimeout(resolve, 2500);
    }).then(() => {
      script.remove();
      file.contents = Buffer.from(dom.serialize());
      this.push(file);
      callback();
    });
  });
}

如果有人知道使用 gulp-tap 这个函数会是什么样子,请随时 post 回答!