Search code examples
node.jsarrayscsvfscsv-parser

csv-parser .on('end') nodeJS


I have this function bd() that should return an arrays of all the data read in the file groupes.csv which will be later processed :

    function bd() {
const birthdays = [];  
    fs.createReadStream('./data/groupes.csv')
            .pipe(csv({}))
            .on('data', (data) => birthdays.push(data))
            .on('end', () => {
              console.log(birthdays)
          });
}  

The console does show the birthday array, my problem is returning it.

I want this function to return the birthdays array. I haven't been successful.

When I put the return statement inside the .on('end') block it doesn't work (for some reason) [maybe the return statement should be outside the fs.read] and if I do that (put it after the .on('end') block), the arrays seems to be empty even after waiting for it to finish using a while loop.


Solution

  • I linked the old post but you don't seem to have understood the underlying issue with the code.

    The .on() function is used to tell the program to call the function inside it when the evet is called which in this case is end, so how do we apply this to the code you have written?

    The function inside your .on('end', () => {}); is called as soon as it has finished reading and thus your birthdays array will be populated when this callback is called.

    This will cause the code to be able to continue running even though the stream has not yet finished and by the time that it would get to print your birthdays array into the console the birthdays array has not yet begun to get populated.

    So how do we fix this? Simple: We use whats called a promise.

    A promise is what you think it is. It's a promise that this function will return something later and promises to give that data when it's available.

    Here is an example of how your function would look when using a promise:

    function bd() {
        return new Promise((resolve, reject) => {
            const birthdays = [];
            fs.createRedStream('./data/groupes.csv')
                .pipe(csv({}))
                .on('data', (data) => birthdays.push(data))
                .on('end', () => {
                    resolve(birthdays);
                });
        });
    }
    

    So what actually happened here?

    We created a new promise object and passed a new callback parameter into it which contains the original code of our function as well as take in 2 parameters from the callback. These 2 functions are what we use for error handling (.catch()) and for fulfilling our promise that we made to return the data or our resolve function.

    This resolve function is basically what we use instead of return.

    So how do we use a promise later in our code?

    We use the .then() function that will get called whenever the promise is resolved.

    bd().then((birthdays) => {
        /* Code */
    });
    

    If you do not understand the core concept of how a Promise works then I can promise you (pun intended) that js might become a problem for you. I suggest that you do not just take the code provided and instead try to understand how it works.

    You can read more on how promises work on MDN