如何使用 csv-parse 避免等待...
Posted
技术标签:
【中文标题】如何使用 csv-parse 避免等待...【英文标题】:How to avoid for await...of with 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()
【参考方案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+,那么请检查带有流/承诺的示例,我已经更新了我的答案以上是关于如何使用 csv-parse 避免等待...的主要内容,如果未能解决你的问题,请参考以下文章