【问题标题】:How to avoid for await...of with csv-parse如何使用 csv-parse 避免等待...
【发布时间】:2022-01-21 16:44:38
【问题描述】:

我希望接受有关此问题的教育,因为我花了几天时间试图自己解决它,但无济于事。

我正在使用 csv-parse 解析 CSV 文件。
我正在使用 ESLint 作为我的 Linter
我正在为 ESLint 使用 Airbnb JavaScript Style Guide 插件
我正在使用 NodeJS 在后端运行它

我的功能是:

const { parse } = require('csv-parse');
const fs = require('fs');
const csvFile = 'myCsvFile.csv';

async function parseCsv(csvFile) {
  const records = [];
  const parser = fs.createReadStream(csvFile).pipe(parse({ delimiter: ',', columns: true }));
  for await (const record of parser) {
    records.push(record);
  }
  return records;

该功能运行良好,但是我正在尝试遵守 Airbnb 的样式指南,它不喜欢 for await...of 循环,因为它违反了 no-restricted-syntax

我很好奇是否有更好的方法来编写此代码以符合 Airbnb 的样式指南,或者如果这是可以忽略违规的情况之一?

【问题讨论】:

  • 嗯,你所链接的任何Airbnb推理是否引起了你的共鸣?
  • 为什么?这执行了我们的不可变规则。处理返回值的纯函数比副作用更容易推理。这似乎不适用于您的情况。
  • @Bergi,好问题。不,它没有引起我的共鸣,这就是我问的原因。我才刚刚踏上这段旅程的几年,有时我需要帮助才能透过树木看到森林。看似简单的事情,我仍然怀念。
  • @JeremyM 然后我建议不要使用该样式指南(或至少不要使用该规则)。 Imo,airbnb 有点误导,经常阻止你使用现代语法。
  • @EmielZuurbier 在某种程度上,确实如此,records.push(record) 是一个副作用。问题是目前节点流(或异步迭代器)上没有帮助方法可以缓解这种情况 - 但是使用iterator helpers proposal,您可以将所有这些简化为const records = await parser.toArray()

标签: javascript node.js eslint airbnb-js-styleguide csv-parse


【解决方案1】:

风格指南说:

11.2 暂时不要使用生成器。 为什么?它们不能很好地转换为 ES5。

幸运的是,如果您使用的是最新的 NodeJS 版本,则无需向下转换,并且可以使用引擎的原生支持。对于浏览器,此建议也很快过时了。

【讨论】:

    【解决方案2】:

    根据答案中给出的建议,我将忽略Airbnb Style Guide 并使用Async iterator 方法。

    最终代码:

    const { parse } = require('csv-parse');
    const fs = require('fs');
    const path = require('path');
    const debug = require('debug')('app:csv:service');
    const chalk = require('chalk');
    
    async function parseCsv(csvFile) {
      try {
        const records = [];
        const stream = fs.createReadStream(csvFile);
        const parser = stream.pipe(parse({ delimiter: ',', columns: true }));
        // eslint-disable-next-line no-restricted-syntax
        for await (const record of parser) {
          records.push(record);
        }
        return records;
      } catch (error) {
        debug(`${chalk.red('Failed')} to parse CSV`);
        debug(`${chalk.red('ERROR:')} ${error}`);
        throw error;
      }
    }
    

    可能是时候寻找新的样式指南来遵循了。感谢 num8er 提供代码建议(我采纳了您的一个想法,使我的代码更具可读性)。

    【讨论】:

      【解决方案3】:

      使用事件结束返回承诺怎么样?

      const { parse } = require('csv-parse');
      const fs = require('fs');
      const csvFile = 'myCsvFile.csv';
      
      async function parseCsv(csvFile) {
        return new Promise((resolve) => {
          const records = [];
          const stream = fs.createReadStream(csvFile);
          const parser = stream.pipe(parse({ delimiter: ',', columns: true }));
          
          parser.on('readable', () => {
            while (record = parser.read()) {
              records.push(record);
            }
          });
      
          let ended = false;
          const end = (error) => {
            if (error) {
              console.error(error.message);
            }
      
            if (!ended) {
              ended = true;
              resolve(records);
            }
          };
      
          parser.on('error', end);
          parser.on('end', end);
        });
      }
      

      如果您有节点 15+,请尝试 stream/promises 示例:

      const { parse } = require('csv-parse');
      const fs = require('fs');
      const { finished } = require('stream/promises');
      const csvFile = 'myCsvFile.csv';
      
      async function parseCsv(csvFile) {
          const records = [];
          const stream = fs.createReadStream(csvFile);
          const parser = stream.pipe(parse({ delimiter: ',', columns: true }));
      
          parser.on('readable', () => {
            let record;
            while ((record = parser.read()) !== null) {
              records.push(record);
            }
          });
      
          await finished(parser);
      
          return records;
      }
      

      【讨论】:

      • 如果将 3 行 for 循环替换为 20 行回调和手动承诺解析使代码兼容,我真的会质疑样式指南...
      • @JonasWilms 我试图让代码没有异步/等待,我认为这是让它更兼容旧的 lts 东西的原因:)
      • 我能够让它作为一个 Promise 工作,但我同意@Jonas Wilms,它需要更多的代码才能让它工作。我开始质疑风格指南。不过这会动摇我的世界?。 3 年前,我开始了这段旅程,强迫自己按照 Airbnb 风格指南学习。对我来说,这几乎是一种宗教。
      • @JeremyM 你可以使用on_record 并简化我的代码,csv.js.org/parse/options/on_record
      • @JeremyM 如果您使用的是节点 15+,那么请检查带有流/承诺的示例,我已经更新了我的答案
      猜你喜欢
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      相关资源
      最近更新 更多