1

With code below I am reading .csv file:

    var fileInput = document.getElementById("uploaded-file");
    var reader = new FileReader();
    reader.onload = function () {
        var students_data = reader.result.split(/\r?\n|\r/);
        for(var count = 1; count<students_data.length; count++){
               var str_students_information = students_data[count];
               var arr_students_information = str_students_information.split(',');
               var a_student_info = [
                   {name: 'student', value: 'add-student'},
                   {name:"id",value:arr_students_information[0]},
                   {name:"name",value:arr_students_information[1]},
                   {name:"mname",value:arr_students_information[2]},
                   {name:"sname",value:arr_students_information[3]}
               ];
              sendToDatabase(a_student_info);
        }
    };
    reader.readAsBinaryString(fileInput.files[0]);

My goal to achieve is to call method sendToDatabase() every 2 seconds while reading a file. Another way to say, after a line of a document was read call the method and wait 2 seconds before reading next line.
With help of topic setTimeout in for-loop does not print consecutive values I was playing with setTimeout(), but always have not what I need...Probably I am missing something...

Virtual Device
  • 1,650
  • 3
  • 10
  • 26
  • am I correct that you need to call `sendToDatabase` for _each line_ in CSV but not more frequently than one time in every 2 seconds? if it's correct, how large file is? I mean how critical memory consumption could be in real life case? – skyboyer Oct 31 '18 at 19:45
  • Why do you use `if (count != 0)` instead of just initializing `count = 1`? – Barmar Oct 31 '18 at 19:48
  • @skyboyer Absolutely correct. File not big. The main concern here is 2 seconds of waiting. – Virtual Device Oct 31 '18 at 19:48
  • @Barmar , well....I don't have the answer, so I just change the code )) thank you )) – Virtual Device Oct 31 '18 at 19:53

2 Answers2

2

Since you want to do something periodically, you should use setInterval(). Instead of a loop, you increment the array index in the callback function.

var fileInput = document.getElementById("uploaded-file");
var reader = new FileReader();
reader.onload = function() {
  var students_data = reader.result.split(/\r?\n|\r/);
  var count = 1;
  var interval = setInterval(function() {
    if (count >= students_data.length) {
      clearInterval(interval);
      return;
    }
    var str_students_information = students_data[count];
    var arr_students_information = str_students_information.split(',');
    var a_student_info = [{
       {name: 'student', value: 'add-student'},
       {name:"id",value:arr_students_information[0]},
       {name:"name",value:arr_students_information[1]},
       {name:"mname",value:arr_students_information[2]},
       {name:"sname",value:arr_students_information[3]}

    ];
    sendToDatabase(a_student_info);
    count++;
  }, 2000);
};
reader.readAsBinaryString(fileInput.files[0]);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • It works, but partly. After reaching `student_data.length` it continues split the file `Uncaught TypeError: Cannot read property 'split' of undefined ...` – Virtual Device Oct 31 '18 at 20:05
  • Sorry, `>` should be `>=`. – Barmar Oct 31 '18 at 20:08
  • Thank you so much! – Virtual Device Oct 31 '18 at 20:11
  • just a remark: because `setInterval` [may drift](https://stackoverflow.com/questions/985670/will-setinterval-drift)(has just ensured it's still actual) it'd be better to set up slightly larger delay(say, 2300ms). sure, only if your 2s delay is really strict. otherwise you may get <2s delay from time to time – skyboyer Oct 31 '18 at 20:13
  • @skyboyer The drift can be longer, but it should never be shorter than the time you set. So if he wants to make sure it's not done more frequently than every 2 seconds, 2000 is fine. – Barmar Oct 31 '18 at 20:14
  • `var start = +new Date(); var count = 0; var previous, shift = 100; setInterval(function () { previous = start; start = +new Date(); let arr = []; if (previous + shift> start) console.log(previous, start, start - previous - shift, 'drifting :('); if(Math.random()> 0.8) for(let i= 0; i< 20000; i++) {arr.push(i); arr.sort();} }, shift);` I see random CPU load makes some interval delay but it does not shift next interval. so execution happens more frequently than `setInterval` value – skyboyer Oct 31 '18 at 20:25
  • 1
    @skyboyer I see what's going on. The timers are based off the original start time. But since a particular instance may start late, there may be less than `shift` ms to when the next one starts. E.g. they start at T+203, T+401, T+610, T+805, etc. – Barmar Oct 31 '18 at 20:39
  • @Barmar yes, so for op it means some sibling requests may go less than in 2 seconds between. And thanks to you, I've realized it is not drifting so I'm wrong while assuming rootcause. – skyboyer Oct 31 '18 at 20:54
0

I belive this can works:

for(....) {
 .
 .
 .
  (function(student_info) {
      sendToDatabase(student_info); 
  })(a_student_info);
}
Rafael Lima
  • 509
  • 5
  • 13
  • no, since object `a_student_info` is constructed by object literal there is no need to construct closure. there could be an issue only if op needed to refer to `count` variable that is reused through the loop. or if op mutated any variable that should be "frozen" while calling `sendToDatabase`. but it's not the case. – skyboyer Oct 31 '18 at 19:48