用gulp-tap将延迟的函数结果返回到下一个Gulp管道

时间:2019-04-12 06:35:47

标签: javascript promise gulp es6-promise

我正在创建一个简单的静态网站,在开发中,我在其中使用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-tapjsdom基本上使用相关脚本来运行文件以进行API调用并填写Handlebars模板,然后删除这些模板脚本并将已编译的HTML发送回下一个管道。但是在jsdom有足够的时间运行所有脚本之前,我很难将发回新的DOM发送回来。

这是我到目前为止所拥有的:

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发送回下一个管道,还是从该函数中发送一个承诺,然后将该承诺解析到我的{{1 }}任务?

我正在使用Gulp 4。

1 个答案:

答案 0 :(得分:0)

咨询Using setTimeout on Promise Chain之后,我想出了如何在超时后解决承诺。

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());
    });
  });
};

但是,这并不能完全解决我的问题,因为在将新的file发送到gulp任务中的下一个管道之前,我需要等待该承诺解决,但是我找不到任何好的文档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时该功能的外观,请随时发布答案!