【问题标题】:Using KnexJS to query X number of tables?使用 KnexJS 查询 X 个表?
【发布时间】:2017-08-28 22:11:10
【问题描述】:

我在这里遇到了一个独特的情况,我无法以优雅的方式解决。

用户传递了他们想要为其导出数据的信号数组。这个数组可以是 1 -> Any_Number 所以首先我会根据传递的信号获取表名(每个信号将数据存储在一个单独的表中)并将它们存储在一个对象中。

下一步是迭代该对象(其中包含我需要查询的表名),对每个表执行查询并将结果存储在一个对象中,该对象将传递给 Promise 中的下一个链。我没有在网上看到任何处理这个问题的好方法的例子,但我知道这是一个相当独特的场景。

在尝试添加对信号数组的支持之前,我的代码如下:

exports.getRawDataForExport = function(data) {
  return new Promise(function(resolve, reject) {

    var getTableName = function() {
      return knex('monitored_parameter')
        .where('device_id', data.device_id)
        .andWhere('internal_name', data.param)
        .first()
        .then(function(row) {
          if(row) {
            var resp = {"table" : 'monitored_parameter_data_' + row.id, "param" : row.display_name};
            return resp;
          }
        });
    }

    var getData = function(runningResult) {
      return knexHistory(runningResult.table)
        .select('data_value as value', 'unit', 'created')
        .then(function(rows) {
          runningResult.data = rows;
          return runningResult;
        });
    }

    var createFile = function(runningResult) {

      var fields = ['value', 'unit', 'created'],
          csvFileName = filePathExport + runningResult.param + '_export.csv',
          zipFileName = filePathExport + runningResult.param + '_export.gz';

      var csv = json2csv({data : runningResult.data, fields : fields, doubleQuotes : ''});

      fs.writeFileSync(csvFileName, csv);

      // create streams for gZipping
      var input = fs.createReadStream(csvFileName);
      var output = fs.createWriteStream(zipFileName);

      // gZip
      input.pipe(gzip).pipe(output);

      return zipFileName;

    }

    getTableName()
      .then(getData)
      .then(createFile)
      .then(function(zipFile) {
        resolve(zipFile);
      });
  });
}

显然,这对于单个表来说很好,我已经更新了 getTableName() 和 createFile() 方法来处理数据数组,所以这个问题只与 getData() 方法有关。

干杯!

【问题讨论】:

    标签: mysql arrays node.js promise knex.js


    【解决方案1】:

    这类问题绝非独一无二,只要采取正确的方法,就可以非常简单地解决。

    不要重写这三个内部函数中的任何一个。

    只需从.getRawDataForExport() 中清除explicit promise construction antipattern,使其返回自然发生的承诺并将异步错误传播给调用者。

    return getTableName()
    .then(getData)
    .then(createFile);
    

    现在,.getRawDataForExport() 是您多次“获取”的基本构建块。

    然后,一个设计选择;并行与顺序操作。两者都有很好的记录。

    平行:

    exports.getMultiple = function(arrayOfSignals) {
        return Promise.all(arrayOfSignals.map(getRawDataForExport));
    };
    

    顺序:

    exports.getMultiple = function(arrayOfSignals) {
        return arrayOfSignals.reduce(function(promise, signal) {
            return promise.then(function() {
                return getRawDataForExport(signal);
            });
        }, Promise.resolve());
    };
    

    首先,为了获得最佳的潜在性能,请尝试并行。

    如果服务器在并行操作中阻塞或可能阻塞,请选择顺序。

    【讨论】:

    • 这是一个很好的建议,我觉得它可以为我在 JS 中处理这些类型的事件打开全新的大门......也就是说,你能详细说明一下吗?你提到的事情?一个简短的示例展示如何打破反模式以及解决/拒绝发生的位置会有所帮助。我看到它的方式,.getRawDataForExport() 已经返回了一个 Promise,不是这样吗?再次感谢!
    • @NicholasKreidberg,对不起我的错。你确实已经在兑现承诺了。编辑后的文字应该更有意义。
    猜你喜欢
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2018-09-01
    相关资源
    最近更新 更多