json2csv icon indicating copy to clipboard operation
json2csv copied to clipboard

Data transforms error handling

Open CarlosVilasAlvarez opened this issue 2 years ago • 3 comments

Hi, I'm having some trouble handling errors caused on data transform functions. json2csv: 5.0.7 Node v16.13.2

When you run this code

const { AsyncParser } = require('json2csv');
const { Readable } = require('stream');

const mockData = [
  {
    id: 1,
    name: 'John',
    surname: 'Doe',
  },
  {
    id: 2,
    name: 'Jane',
    surname: 'Doe',
  }
];

const mockDataStream = Readable.from(mockData);

const dataTransform = (data) => {
  if (data.name === 'Jane') throw new Error('Unhandled error');
  return data;
};

const asyncParser = new AsyncParser({ transforms: [dataTransform] }, { objectMode: true });

try {
  const parsingProcessor = asyncParser.fromInput(mockDataStream).toOutput(process.stdout);
  parsingProcessor.promise(false).catch(err => {
    console.log('Something happened');
  });
} catch (error) {
  console.log('Hello?');
}

You cannot handle the exception, it'll be an unhandledException one.

Screenshot 2022-09-20 at 15 40 36

Only approach that works is to put a try catch inside the data transform function like this.

const dataTransform = (data) => {
  try {
    if (data.name === 'Jane') throw new Error('Unhandled error');
    return data;
  } catch (error) {
    return undefined;
  }
};

CarlosVilasAlvarez avatar Sep 20 '22 13:09 CarlosVilasAlvarez

This does not happen in v6 which was just published as a separate package: https://www.npmjs.com/package/@json2csv/node

Although, the API has changed to make the async api more similar than the other. Also, when piping to an output stream the promise method has been removed since it's trivial to wait for the end event and node nowadays even provides the pipeline method for that. In v6 you can do:

const { pipeline } = require('node:stream/promises');

// ...

try {
  pipeline(asyncParser.parse(mockDataStream), process.stdout).catch(err => {
    console.log('Something happened');
  });
} catch (error) {
  console.log('Hello?');
}

or using the transform

const json2csvTransform = new Transform({ transforms: [dataTransform] }, { objectMode: true });

try {
  pipeline(mockDataStream, json2csvTransform, process.stdout).catch(err => {
    console.log('Something happened');
  });
} catch (error) {
  console.log('Hello?');
}

I haven't tested the code. It's just a quick guidelines. If you have more issues with it I can look deeper into it.

juanjoDiaz avatar Sep 27 '22 16:09 juanjoDiaz

Thank you @juanjoDiaz I didn't know that package existed, is this repo "deprecated" then? I think I'll just migrate all the code from v5 to the new v6.

CarlosVilasAlvarez avatar Sep 27 '22 18:09 CarlosVilasAlvarez

Yup. I'd consider it deprecated. And I think that you'd do well moving to v6 🙂

juanjoDiaz avatar Sep 27 '22 20:09 juanjoDiaz