1

I have a for loop iterating over the number of files

I have to read the first line of each file and add it let's say to a Map having File name as the key and First line of that file as a the value.

I am using FileReader to read the file but it is asynchronous.

When I open a stream to read the file the loop gets incremented before I am done with reading the file and adding my desired entry to the map.

I need a synchronous operation i.e. Read the First line , add it to the Map and then increment the loop and proceed with the next file.

for (var i = 0; i < files.length; i++){

    var file = files[i];

    var reader = new FileReader();

    reader.onload = function(progressEvent){
    var lines = progressEvent.target.result.split('\n');
    firstLine = lines[0];
    alert('FirstLine'+firstLine);   
    //add to Map here 
    }

    reader.readAsText(file);
}

How to modify the code so as to achieve the above mentioned functionality.

3
  • To synchronize a process you can use recursion or promise chain Commented May 31, 2016 at 6:16
  • @Rajesh could you please help me with it, am not a pro working with JS. Commented May 31, 2016 at 6:32
  • you can try something like this: JSFiddle. This is a sample code. Commented May 31, 2016 at 6:52

2 Answers 2

3

You can use promises and let them run in the order you create them using reduce.

The below code shows how it could be done this way, and you can take a look at this simple JSFiddle that demos the idea.

//create a function that returns a promise
function readFileAndAddToMap(file){
    return new Promise(function(resolve, reject){
        var reader = new FileReader();
        reader.onload = function(progressEvent){
            var lines = progressEvent.target.result.split('\n');
            firstLine = lines[0];
            console.log('FirstLine'+firstLine);   
            //add to Map here 
            resolve();
        }

        reader.onerror = function(error){
            reject(error);
        }

        reader.readAsText(file);
    });
}

//create an array to hold your promises
var promises = [];
for (var i = 0; i < files.length; i++){
    //push to the array
    promises.push(readFileAndAddToMap(files[i]));
}

//use reduce to create a chain in the order of the promise array
promises.reduce(function(cur, next) {
    return cur.then(next);
}, Promise.resolve()).then(function() {
    //all files read and executed!
}).catch(function(error){
    //handle potential error
});
Sign up to request clarification or add additional context in comments.

Comments

0

I was facing the same issue, what I did was I removed the for loop and used recursive function instead. That way, I was able to handle the sequence of FileReader.

Below I tried to modify your code based on my logic. feel free to ask any question in comments if you need more clarity.

attachmentI = { i: files.length };

function UploadMe() {
   attachmentI.i--;
   if(attachmentI.i > -1){
      var file = files[attachmentI.i];
      var reader = new FileReader();
      reader.onload = function(progressEvent){
         var lines = progressEvent.target.result.split('\n');
         firstLine = lines[0];
         alert('FirstLine'+firstLine);   
         //add to Map here
         UploadMe();
      }
   reader.readAsText(file);
   }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.