如何在JavaScript中正确导出CSV解析结果供其他文件调用?
解决CSV读取模块被require时无法返回目标数组的问题
问题背景
当前main.js通过readline异步读取CSV文件并处理数据,单独运行时能输出正确的目标数组,但在其他文件中require('./main')时,因异步操作特性,只能拿到空对象,无法直接用于后续金额计算逻辑。
当前main.js代码
const fs = require('fs'); const readline = require("readline"); const stream = fs.createReadStream("./data.csv"); const rl = readline.createInterface({ input: stream }); let data = []; let header = []; rl.on("line", (row) => { if (header.length === 0) { // 处理表头行 header = row.split(";"); } else { // 处理数据行 const rowData = row.split(";"); const obj = {}; // 将数据行转为对象 for (let i = 0; i < header.length; i++) { obj[header[i]] = rowData[i]; } // 将对象加入数据数组 data.push(obj); } }); rl.on("close", () => { let hasil_mentah = []; for (let k = 0; k < data.length; k++) { const { Nama, Harga } = data[k]; const obj_data = { Nama: Nama.toLowerCase(), // 将名称转为小写 Harga: parseInt(Harga) // 将价格转为整数类型 }; hasil_mentah.push(obj_data); } console.log(hasil_mentah); });
引入时的问题
当在其他文件中执行以下代码:
const dataset = require('./main'); console.log(dataset);
输出为:
{} [ { Nama: 'kangkung', Harga: 3000 }, { Nama: 'telur', Harga: 2500 }, { Nama: 'cabai', Harga: 5000 }, { Nama: 'bawang putih', Harga: 4000 }, { Nama: 'bawang merah', Harga: 6000 }, { Nama: 'tempe', Harga: 7000 }, { Nama: 'tahu', Harga: 8000 } ]
无法直接将dataset作为数组用于后续计算。
期望的使用场景
需要在金额计算代码中直接获取目标数组:
const prompt=require("prompt-sync")({sigint:true}); const dataset = require('./main'); var input = prompt("Masukkan Uang Anda: "); var uang = parseInt(input); for (let count = 0; count < dataset.length; count++) { const variabel = dataset[count]; console.log("Nama : "+ variabel.nama); console.log("harga : "+ variabel.harga); var hasil_desimal = uang/variabel.harga; var hasil_bulat = Math.floor(hasil_desimal); console.log("jumlah dapat : "+ hasil_bulat); console.log('-----'); }
解决方案
CSV读取是异步操作,require是同步执行的,因此需要将main.js的逻辑包装成Promise,通过异步方式获取处理后的数据。
修改后的main.js
将读取和处理逻辑封装在Promise中,并导出这个Promise:
const fs = require('fs'); const readline = require("readline"); // 封装为Promise module.exports = new Promise((resolve, reject) => { const stream = fs.createReadStream("./data.csv"); const rl = readline.createInterface({ input: stream }); let data = []; let header = []; rl.on("line", (row) => { if (header.length === 0) { header = row.split(";"); } else { const rowData = row.split(";"); const obj = {}; for (let i = 0; i < header.length; i++) { obj[header[i]] = rowData[i]; } data.push(obj); } }); rl.on("close", () => { const hasil_mentah = data.map(item => { return { nama: item.Nama.toLowerCase(), // 统一为小写键名,匹配后续计算代码中的variabel.nama harga: parseInt(item.Harga) // 统一为小写键名,匹配variabel.harga }; }); resolve(hasil_mentah); // 将处理后的数组作为Promise结果返回 }); // 处理读取错误 rl.on("error", (err) => { reject(err); }); });
修改后的引入文件(金额计算代码)
使用async/await来获取Promise返回的数组:
const prompt = require("prompt-sync")({ sigint: true }); // 用async函数包裹逻辑,await获取数据 async function calculate() { const dataset = await require('./main'); var input = prompt("Masukkan Uang Anda: "); var uang = parseInt(input); for (let count = 0; count < dataset.length; count++) { const variabel = dataset[count]; console.log("Nama : " + variabel.nama); console.log("harga : " + variabel.harga); var hasil_desimal = uang / variabel.harga; var hasil_bulat = Math.floor(hasil_desimal); console.log("jumlah dapat : " + hasil_bulat); console.log('-----'); } } // 执行函数 calculate();
关键说明
- 异步处理:通过Promise封装异步读取逻辑,确保数据处理完成后才返回结果。
- 键名统一:将处理后对象的键名改为
nama和harga(小写),匹配计算代码中的引用,避免出现undefined问题。 - 错误处理:添加
error事件监听,读取文件出错时会拒绝Promise,方便后续捕获错误。
内容的提问来源于stack exchange,提问作者3IA04_Iqbal Al Fakhri
相关产品推荐
相关产品推荐

