Search code examples
javascriptpromisees6-promisepapaparse

Iterating over results of papa.parse object


I believe this may be an issue with async or promises, however, this concept has been a struggle for me to grasp. I have spent much time researching questions relating to papaparse and promises, but believe I am still not grasping some simple concept.

Overview

In the below code, a .csv file is gathered from the user, converted into an Object using PapaParse, then distance/duration values are added to the data from GoogleMaps Distance Matrix and finally, the intent is to return this data back to the user as a .csv containing this combined information.

In downloadCSV(), I am able to log the Object which results from getDistTime. However, I am unable to iterate over this object or send it to papa.unparse to convert to a .csv. Below the code, I have attached an image of the structure of arr within downloadCSV().

I have spent much time researching questions here, and on the papaparse repo. I would appreciate any help on how to best proceed.

Contents of arr: I'm good

Code


    $("#submit").click(function(){
        //REMOVE THIS LINE BEFORE LIVE OR VALIDATION WILL BE DUN GOOFED
        event.preventDefault();
        getData();
    });


    function getData(){
        var csv = document.getElementById('exampleFormControlFile1').files[0];
        // Parse CSV string
        Papa.parse(csv, {
            header: true,
            complete: function(results) {
                var final_rows = getDistTime(results)
                downloadCSV(final_rows) 
            }
        });
    } // end getData


    function downloadCSV(arr){
        //console.log(arr) shows the results
        // but trying to iterate over arr or unparsing shows undefined
        console.log(arr)
        csv = Papa.unparse(arr)

       ...more csv export code
    }


    function getDistTime(resources){
        var rows = []
        const promiseArr = [];
        for (var i = 0; i < resources.data.length; i++) {
            var origin1 = $("#citystate").val();;
            var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
            promiseArr.push(googleRequest(origin1, destinationA));
        }

        Promise.all(promiseArr)
        .then((resultsArr) => {
            resultsArr.forEach((result, i) => 
            pushToRows(resources.data[i], result, rows));
        
        })
        return rows
    } // end getDistTime


    function pushToRows(resources, dist_dur, rows){
        resources["DISTANCE_MI"] = dist_dur[0];
        resources["ACTUAL_DUR_HR"] = dist_dur[1];
        resources["FINANCE_DUR_HR"] = (dist_dur[0] / 45.0).toFixed(2)
        rows.push(resources)   
    } // end pushToRows


Solution

  • getDistTime is performing an async action and therefore rows is returning empty before the Promise.all has resolved as you wont have pushed any data to it until that promise resolves.

    Looks like you'll need to await the result of getDistTime or change how get data works, not sure you're using async await so simplest way is to just return that Promise.all and then only download the csv once its returned and resolved in your complete callback.

    for example you could do

    function getData(){
        var csv = document.getElementById('exampleFormControlFile1').files[0];
        // Parse CSV string
        Papa.parse(csv, {
            header: true,
            complete: function(results) {
                getDistTime(results).then(finalRows => downloadCSV(finalRows));
                
            }
        });
    } // end getData
    
    function getDistTime(resources){
        var rows = []
        const promiseArr = [];
        for (var i = 0; i < resources.data.length; i++) {
            var origin1 = $("#citystate").val();;
            var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
            promiseArr.push(googleRequest(origin1, destinationA));
        }
    
        return Promise.all(promiseArr)
        .then((resultsArr) => {
            resultsArr.forEach((result, i) => 
                pushToRows(resources.data[i], result, rows)
            );
        
            return rows
        })
    } // end getDistTime