Gulp:调用一个异步函数,该函数从转换函数中提供自己的回调

Gulp: call an async function which provides its own callback from within a transform function

我想创建一个用于 Gulp 中的 pipe() 调用的函数,它可以将 xlsx 文件转换为 json。

我在 gulp 3 中使用 NPM 包 'excel-as-json',但是 Gulp 4 迫使我真正理解它在做什么 ;-)

六个小时后,由于缺乏 js/async/streaming 知识,我无法让它工作,这激发了我的好奇心。

代码如下:

paths = {excel_sourcefiles: "./sourcefiles/*.xls*", excel_targetdir_local_csvjson: "./targetfiles_local/*.*"}


var replaceExt = require('replace-ext');
var PluginError = require('plugin-error')
var gulpFunction = require('gulp-function').gulpFunction // default ES6 export
var through = require("through2")
var convertExcel = require('excel-as-json').processFile;
var changed = require('gulp-changed');
var assign = Object.assign || require('object.assign');
var notify = require('gulp-notify');
var gulpIgnore = require('gulp-ignore');
var rename = require('gulp-rename');

gulp.task('excel-to-jsoncsv', function() {
  return gulp.src(paths.excel_sourcefiles)
    // .pipe(debug())
    .pipe(gulpIgnore.exclude("*\~*")) // Ignore temporary files  by Excel while xlsx is  open
    .pipe(gulpIgnore.exclude("*$*")) // Ignore temporary files  by Excel while xlsx is  open
    .pipe(plumber({errorHandler: notify.onError('gulp-excel-to-jsoncsv error: <%= error.message %>')}))
    .pipe(changed(paths.excel_targetdir_local_glob, { extension: '.csv' }))
    .pipe(GulpConvertExcelToJson()) // This is where the magic should happen
    .pipe(rename({ extname: '.csv' })) // Saving as .csv for SharePoint (does not allow .json files to be saved)
    .pipe(gulp.dest(paths.excel_targetdir_local))
});

function GulpConvertExcelToJson() {
  return through.obj(function(chunk, enc, callback) {
    var self = this
    if (chunk.isNull() || chunk.isDirectory()) {
      callback() // Do not process directories
      // return
    }

    if (chunk.isStream()) {
      callback() // Do not process streams
      // return
    }

    if (chunk.isBuffer()) {
      convertExcel(chunk.path, null, null, // Converts file found at `chunk.path` and returns (err, `data`) its callback.
        function(err, data) {
          if (err) {
            callback(new PluginError("Excel-as-json", err))
          }
          chunk.contents = new Buffer(JSON.stringify(data))
          self.push(chunk)
          callback()
          // return
        })
    } else {
      callback()
    }
  })
}

我(现在)知道还有其他 excel > json gulp 模块可以让我在不编写自己的模块的情况下解决这个问题,但我想了解我在这里应该做些什么。

返回的错误是'Did you forget to signal Async completion?',我尽量不这样做。但是,我尝试用 var self = this 修复错误 'this.push is not a function' 的尝试可能不是我应该做的。

查看 gulp-zip 之类的示例让我了解了不熟悉的符号,使我无法通过自学来解决这个问题。

总结:

这个问题来自 excel 库。 The end event should be finish.

尝试失败

我做了以下操作,安装修改后的 excel.js:

rm -rf node_modules/excel
git clone https://github.com/bdbosman/excel.js node_modules/excel
cd node_modules/excel && npm i && cd ../..

这还不够,因为 excel-as-json 使用旧版本的 excel

要么您必须修改 excel-as-json 模块,使用 excel@1.0.0(合并请求请求后),或者手动编辑 node_modules 中的文件。我这里介绍第二种方式。

临时解决方案

安装模块后编辑 excel 文件。

我用过:

sed -i "s/'end'/'finish'/g" node_modules/excel/excelParser.js

然后我运行:

$ gulp excel-to-jsoncsv
[19:48:21] Using gulpfile ~/so-question-gulp-async-function-call-xlsx/gulpfile.js
[19:48:21] Starting 'excel-to-jsoncsv'...
[19:48:21] Finished 'excel-to-jsoncsv' after 126 ms

而且它显然奏效了。