Search code examples
javascriptcallbackpapaparse

Callbacks in JavaScript


A rookie question, but I am trying to understand how PapaParse (or anything else, for that matter) uses callbacks. When I use the following code:

Here is the revised full code:

<html>
    <head>
    <script src="papaparse.js"></script>
    <script src="drawTable.js"></script> 

</head>
<body>  
 <label>Load CSV file: </label><input type="file" id="fileInputCSV" /><br/>

    Results: 
    <table id="outputTable" border=1 px>
        <tbody id="objTable"></tbody>
    </table>


  <script type="text/javascript">      
 var csvData = [];  
 function GetCSV(doneCallback) {
   var fileInput = document.getElementById('fileInputCSV'); 
       Papa.parse(fileInput.files[0], {
       header: true,
       skipEmptyLines: true,

       complete: function(results) {
       console.log('Done.');
       doneCallback(results);
    }
   });
 }
}

GetCSV(function(csvData) {
    console.table(csvData.data);
   drawTable(csvData.data, "objTable");
});
    </script>
    </body>
</html>

I have to reload the page to get the console.table, and the object generated by PapaParse is unavailable outside the PapaParse function.

I know this has been asked in other forms, but always has been answered in jQuery. Is there a solution is plain JavaScript? I really need not just to be able to display the data, but actually to be able to use it.

PapaParse itself is noticeably quiet on such a basic use of their program....

Thanks!


Solution

  • All code that wants to use an asynchronous result reliably as soon as it is available MUST be either located inside the completion callback function or must be in a function that is called from that callback function.

    This is because an asynchronous response happens sometime LATER at an indeterminate time. The ONLY place in your code where you can know exactly when the result is ready is inside the completion callback itself. It is a very bad practice to try to stuff an asynchronous result in some higher scoped variable and then use it later because your other code will have no idea when that value is actually available - generally leading to all sorts of timing issues.

    This is a different type of programming than sequential programming. You don't just call getCSV() and then use the results from that on the next line of code. The results won't be available until some time later.

    If you wanted to know when the results to getCSV() were available, you would construct it so that it takes a callback:

    function GetCSV(doneCallback) {
       var fileInput = document.getElementById('fileInputCSV'); 
       Papa.parse(fileInput.files[0], {
           header: true,
           skipEmptyLines: true,
    
           complete: function(results) {
               console.log('Done.');
               doneCallback(results);
            }
        });
     }
    

    Then, you can call it like this and consume the results inside the callback:

    GetCSV(function(csvData) {
        // use the data here
         drawTable(csvData.data, "objTable");
    });