Luke
Luke

Reputation: 3541

why does this alert fire before earlier code has finished executing?

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.

Upvotes: 2

Views: 959

Answers (2)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

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.

Upvotes: 1

Vivin Paliath
Vivin Paliath

Reputation: 95508

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();
    }
}

Upvotes: 1

Related Questions