2

I have some javascript code which executes when a link is clicked.

after that code has executed I want to display an alert, however the alert is being shown before the earlier code completes

document.querySelector('.btn-primary').addEventListener('click', function(evt) {

    var loops = 10;
    var chunkLength = Math.ceil(file.size / loops);
    var start = 0;
    var stop = chunkLength;

    for (var i = 0; i < loops; i++) {
        var blob = file.slice(start, stop);
        readText(blob);
        start = stop;
        stop += chunkLength;
    }
    alert('entire file loaded');
    print();
}, false);

updates

I know because the readText method updates a progress bar and this happens after the alert pops up, its not an ajax call just a local method (which is asynchronous...)

eventually, I'm looking to replace the alert with a call to save a file but its no use if the file content hasn't been generated yet as I just save an empty file.

Luke
  • 3,481
  • 6
  • 39
  • 63

2 Answers2

1

You mentioned that readText is an asynchronous method. This is why the alert shows before readText has finished executing. The for loop will run through all its iterations by which time calls to readText have not finished. The next statement to execute after the for, is the alert which is what you're seeing.

If readText provides a callback function, you will have to use that:

var counter = 0;
for (var i = 0; i < loops; i++) {
    var blob = file.slice(start, stop);
    readText(blob, function() {
        counter++;
        if(counter === loops) {
            alert("entire file loaded");
        }
    });
    start = stop;
    stop += chunkLength;
}

This doesn't guarantee order of operations however. It is entirely possible that a call on a later iteration finishes before a call from an earlier iteration.

If readText doesn't have a callback argument and you can modify the source of that function, you will have to do something like this:

function readText(blob, callback) {
    ...

    if(typeof callback === "function") {
        callback();
    }
}
Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
1

In that case, you'll need to extend readText to accept a callback function:

function readText(blob, callback) {
    var reader = new FileReader();
    reader.onload = callback;
    // whatever else your function does to load the file
}

Then you invoke it like this:

readText(blob, function() {
    alert('entire file loaded');
});

Of course if readText itself delegates its asynchronous work somewhere else, you'll have to pass the callback there too.

If the actual asynchronous function doesn't accept a callback parameter, you'll want to check for another way that it signals its caller of completeness. It may fire events. But that all really depends on how readText is implemented.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • `readText`is basically a wrapper for the `FileReader.readAsText(blob)`I don't think it accepts a callback but I can look it up - thanks! – Luke Nov 08 '13 at 22:39
  • `FileReader.readAsText` indeed doesn't have a callback.. But `FileReader` has on onload event that you can hook into. https://developer.mozilla.org/en-US/docs/Web/API/FileReader.onload I'll see if I can update my code snippets with that knowledge. – Frank van Puffelen Nov 08 '13 at 22:41
  • unfortunately multiple onload events are fired (one for each chunk loaded) and theres no way of telling which one is the last one. So i'll need to think of something else. I might only show a save button once the progress bar is fully loaded – Luke Nov 08 '13 at 22:44