I have these excel file contains columns : No, itemCode, startAt, endAt
I loop the data using createReadStream
And I want to detect the invalid datetime from excel file and write the error into test.txt file
Here's my current code
const csv = require('csv-parser');
const fs = require('fs');
const moment = require('moment');
const yesql = require('yesql');
const _ = require('lodash');
const { exit } = require('process');
async function run() {
fs.createReadStream('test.csv')
.pipe(csv())
.on('data', (data) => csvResults.push(data))
.on('end', async () => {
const groups = _.groupBy(csvResults, item => item['itemCode']);
for (const itemCode in groups) {
for (const item of groups[itemCode]) {
const startDateTime = moment(item['startAt'], 'YYYY-MM-DD HH:mm:ss');
const endDateTime = moment(item['endAt'], 'YYYY-MM-DD HH:mm:ss');
if (startDateTime.isAfter(endDateTime)) {
console.error(`Datetime invalid ${item['No']}`);
// Want to write into file if got an error
var stream = fs.createWriteStream("test.txt");
stream.once('open', function(fd) {
stream.write(`${item['No']} : ${startDateTime} ${endDateTime} \n`);
stream.end();
});
continue;
}
}
}
exit();
});
}
run();
Your for
loop does NOT wait for the fs.createWriteStream()
stuff to complete so you end up trying to write to the same file multiple times at the same time which creates a mess in that file. Likewise, you call exit()
before your writes are even done also because the for loop doesn't wait for the stream to finish.
If what you want to do is to append each error condition to your file, then you can do it like this:
const csv = require('csv-parser');
const fs = require('fs');
const fsp = fs.promises;
const moment = require('moment');
const yesql = require('yesql');
const _ = require('lodash');
const { exit } = require('process');
async function run() {
fs.createReadStream('test.csv')
.pipe(csv())
.on('data', (data) => csvResults.push(data))
.on('end', async () => {
const groups = _.groupBy(csvResults, item => item['itemCode']);
for (const itemCode in groups) {
for (const item of groups[itemCode]) {
try {
const startDateTime = moment(item['startAt'], 'YYYY-MM-DD HH:mm:ss');
const endDateTime = moment(item['endAt'], 'YYYY-MM-DD HH:mm:ss');
if (startDateTime.isAfter(endDateTime)) {
console.error(`Datetime invalid ${item['No']}`);
// append into file if got an error
await fsp.appendFile("test.txt", `${item['No']} : ${startDateTime} ${endDateTime} \n`);
}
} catch(e) {
console.log(e);
// not sure what you want to do here if you got an error while appending to the file
}
}
}
exit();
});
}
run();
If you want to just record the first error in the file and then stop further processing, you can use fsp.writeFile()
instead of fsp.appendFile()
and put your call to exit()
right after that call.