Monday, March 30, 2015

Callback JavaScript


JavaScript statements are executed line by line. However, with effects, the next line of code can be run even though the effect is not finished. This can create errors.
To prevent this, you can create a callback function. A callback function is executed after the current effect is finished.
Let's start with a very simple script that uses no callbacks. First we'll establish a super-quick HTML structure to output results to:
<html>
    <body>
        <p id="result">
        </p>
    </body>
</html>

And then we'll add a bit of JavaScript:

document.getElementById('result').innerHTML += ('starting ...');
document.getElementById('result').innerHTML += ('continuing ...');

document.getElementById('result').innerHTML += ('ending!');

Go ahead and run it for yourself. So, great … as you can see when you run this, it prints "ending!" before "continuing …" pretty much exactly as expected. And no good. We don't want to end in the middle. We want to end at the end.
So let's do that.
SETTIMEOUT() - FIRST CALLBACK
JavaScript has a function for delayed execution of commands. You give it a command to run, and the number of milliseconds to wait before running it. It's handy for a variety of reasons, but its value here is that when you use it, your JavaScript interpeter (in my case, Chrome … but any browser, as well as Node, will do the same) considers it an asynchronous, non-blocking request. Here's our new code:
document.getElementById('result').innerHTML += ('starting ...');
var myTimer = window.setTimeout(function() {
    document.getElementById('result').innerHTML += ('ending!');
}, 500);

document.getElementById('result').innerHTML += ('continuing ...');

check that out.Now we're back to having the right order in our output, even though the code's not sequential, because we're waiting half a second before executing an anonymous function that writes our "ending!" string. Finding the anonymous function thing confusing? You could also write the code like this:


document.getElementById('result').innerHTML += ('starting ...');

// Wait half a second before firing the writeEnding() function
var myTimer = window.setTimeout(writeEnding, 300);
document.getElementById('result').innerHTML += ('continuing ...');

// Define the Write Ending Function
function writeEnding() {
    // Write "ending!"
    document.getElementById('result').innerHTML += ('ending!');
}

Same exact thing, but now the function's not anonymous because we declared it at the bottom. We're still calling it with setTimeout, though, after 300 milliseconds. 

CREATING OWN CALLBACKS
 We've established that setTimeout uses a callback to enact a delayed execution of a function, but how do we write one of our own? Easy! Like this:


getData('http://javascripttech.blogspot.com/userlist', result);

document.getElementById('result').innerHTML += "show this before data loaded ...";
function getData(dataURI, callback) {
    // Normally you would actually connect to a server here.
    // We're just going to simulate a 2-second delay.
    var timer = setTimeout(function () {
        var dataArray = [123,579,456,258,476,458];
        callback(dataArray);
    }, 2000);
}
function result(myData) {
    document.getElementById('result').innerHTML += myData;

}

If you run this in jsfiddle, you'll see it behaves just as we want it to: even though the getData function is the first thing called, and takes two seconds to run, the script continues right along. When the two seconds are up and getData responds with data, then result fires and writes the data.

Unknown Software Engineer

No comments:

Post a Comment