From 3e296f611522d0f86ab17f5faeed21df1e192583 Mon Sep 17 00:00:00 2001 From: Juanjo Diaz Date: Mon, 9 Sep 2019 20:19:06 +0300 Subject: [PATCH] feat: Improve async promise to optionally not return (#421) --- README.md | 19 +++++++++++++++---- lib/JSON2CSVAsyncParser.js | 9 ++++++++- test/JSON2CSVAsyncParser.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ec979aed..cd37dba0 100644 --- a/README.md +++ b/README.md @@ -269,7 +269,7 @@ asyncParser.input.push(null); // Sending `null` to a stream signal that no more * `fromInput` allows you to set the input stream. * `throughTransform` allows you to add transforms to the stream. * `toOutput` allows you to set the output stream. -* `promise` returns a promise that resolves when the stream ends or errors. +* `promise` returns a promise that resolves when the stream ends or errors. Takes a boolean parameter to indicate if the resulting CSV should be kept in-memory and be resolved by the promise. ```js const { createReadStream, createWriteStream } = require('fs'); @@ -279,12 +279,23 @@ const fields = ['field1', 'field2', 'field3']; const opts = { fields }; const transformOpts = { highWaterMark: 8192 }; +// Using the promise API const input = createReadStream(inputPath, { encoding: 'utf8' }); -const output = createWriteStream(outputPath, { encoding: 'utf8' }); const asyncParser = new JSON2CSVAsyncParser(opts, transformOpts); -asyncParser.fromInput(input).toOutput(output).promise() +const parsingProcessor = asyncParser.fromInput(input); + +parsingProcessor.promise() .then(csv => console.log(csv)) - .catch(err => console.error(err));; + .catch(err => console.error(err)); + +// Using the promise API just to know when the process finnish +// but not actually load the CSV in memory +const input = createReadStream(inputPath, { encoding: 'utf8' }); +const output = createWriteStream(outputPath, { encoding: 'utf8' }); +const asyncParser = new JSON2CSVAsyncParser(opts, transformOpts); +const parsingProcessor = asyncParser.fromInput(input).toOutput(output); + +parsingProcessor.promise(false).catch(err => console.error(err)); ``` you can also use the convenience method `parseAsync` which accept both JSON arrays/objects and readable streams and returns a promise. diff --git a/lib/JSON2CSVAsyncParser.js b/lib/JSON2CSVAsyncParser.js index 2a07d040..6773b732 100644 --- a/lib/JSON2CSVAsyncParser.js +++ b/lib/JSON2CSVAsyncParser.js @@ -39,8 +39,15 @@ class JSON2CSVAsyncParser { return this; } - promise() { + promise(returnCSV = true) { return new Promise((resolve, reject) => { + if (!returnCSV) { + this.processor + .on('finish', () => resolve()) + .on('error', err => reject(err)); + return; + } + let csvBuffer = []; this.processor .on('data', chunk => csvBuffer.push(chunk.toString())) diff --git a/test/JSON2CSVAsyncParser.js b/test/JSON2CSVAsyncParser.js index e936724c..208ad1ac 100644 --- a/test/JSON2CSVAsyncParser.js +++ b/test/JSON2CSVAsyncParser.js @@ -955,4 +955,34 @@ module.exports = (testRunner, jsonFixtures, csvFixtures, inMemoryJsonFixtures) = t.end(); }); + testRunner.add('should not return if ret option is set to false', (t) => { + const parser = new AsyncParser(); + const configuredParser = parser.fromInput(jsonFixtures.default()) + let csv = ''; + + configuredParser.processor.on('data', chunk => (csv += chunk.toString())); + + configuredParser.promise(false) + .then(res => { + t.equal(res, undefined); + t.equal(csv, csvFixtures.defaultStream); + }) + .catch(err => t.notOk(true, err.message)) + .then(() => t.end()); + }); + + testRunner.add('should catch errors even if ret option is set to false', (t) => { + const opts = { + fields: ['carModel', 'price', 'color', 'transmission'] + }; + + const parser = new AsyncParser(opts); + + parser.fromInput(jsonFixtures.defaultInvalid()).promise(false) + .then(() => t.notOk(true)) + .catch(err => t.ok(err.message.includes('Invalid JSON'))) + .then(() => t.end()); + }); + + };