Search code examples
node.jsasynchronousreadfile

How to make while loop with switch case synchrounous in nodejs?


How can I make the while loop with switch-case synchronous in nodejs? Below is the code I am trying to iterate for 2 iterations of the while loop. But the problem is the next iteration gets iterated even before completing all the synchronous functions here which are readdirSync, readFileSync, etc.

What I want is with each whileloop iteration it should run all the methods and then again for next iteration.

Currently the output is:

i =  0
i =  1

Below is my code:

 const dir4Data = 'C:/Users/em/Desktop/Regex_test_case/data/google_forms';
    const dir4Polls = 'C:/Users/em/Desktop/Regex_test_case/Poll_Report';
    var dir, i=0;
    
    var regex4Data = /^\d{1,2}([./-])\d{1,2}\1\d{4}$/;
    var regex4Polls = /^[1-9]\d*$/;
    
    while(i < 2)
    {
      switch (i) {
        case 0:
        dir = dir4Data;
        break;
        case 1:
        dir = dir4Polls;
        break;
      }
    
      console.log('i = ', i);
      fs.readdirSync(dir, function(err,files){    //Get a listing of all the files in the dir
        if (err) throw err;
        files.forEach(function(file){
          //console.log("file = "+ file);
          const writePath = 'C:/Users/em/Desktop/Regex_test_case/output/'+file;
          fs.readFileSync(dir+'/'+file, function(err, data) {
            console.log("data = "+ data);
            var csvContent = data.toString().split('\n'); // read file and convert to array by line break
            csvContent.forEach((item, index) => {
              var csv;
              if(!regex4Data.test(item.toString().split(' ')[0])  && index != 0 && i == 0)  {
                csv = csvContent[index-1].replace(/(\r\n|\n|\r)/gm, ""); // remove the breaks
                //  console.log(index, ' Replaced', csv);
                fs.appendFileSync(writePath, csvContent[index].toString()+ ' ', function (err, data) {
                  if (err) throw err;
                  //console.log('Saved!');
                })
              }
              else if(!regex4Polls.test(item.toString().split(',')[0])  && index != 0 && i == 1)  {
                csv = csvContent[index-1].replace(/(\r\n|\n|\r)/gm, ""); // remove the breaks
                //  console.log(index, ' Replaced', csv);
                fs.appendFileSync(writePath, csvContent[index].toString()+ ' ', function (err, data) {
                  if (err) throw err;
                  //console.log('Saved!');
                })
              }
              else {
                csv = item.toString();
                fs.appendFileSync(writePath, "\n"+csv + " ", function (err, data) {
                  if (err) throw err;
                  //console.log('Saved!');
                })
              }
            });
          })
        })
      })
      i++;
    }

Solution

  • There are two main error in your script.

    First of all, you are using wrong the FS module function.

    From the doc, https://nodejs.org/api/fs.html#fs_synchronous_example, all the FS Sync function are synchronous. That means that you don't have to pass them a callback.

    You can just write

    var response = fs.readFileSync(path);
    

    And the value of response is your file.

    The other thing is, if you wont to iterate an async function, you cannot with callback, but you can do it using async/await.

    Here an example of loop working:

    async function loop() {
        var i = 0
        while (i < 2) {
            var response = await fs.promises.readFile(path);
            console.log(response)
            i++
        }
    }