Originally Posted by
MutantJohn
I'm assuming it's data dependencies that are determining how the instructions are executed here. I could be wrong on that part.
You are pretty much right on that part, if I understand you correctly. I remember someone once saying "You can't have just a little asynchronous code", because introducing it tends to have a ripple effect. Take for instance if we want to write some vanilla JS to make asynchronous requests easier:
Code:
// Let our callback have this signature:
// function (error, data);
function request(options, callback) {
var req = new XMLHttpRequest();
// Remember in JS that the || operator evaluates to the first operand with true-ish value
// (Or the right most operand if none do)
req.open(options.method || "GET", options.path, true);
req.addEventListener("load", function () {
if (req.status < 400) {
callback(null, req.responseText);
} else {
callback(new Error("Network error: " + req.statusText, null);
}
});
// Can add additional callbacks to the request object here...
req.send(options.body || null);
}
Alright, so if I didn't screw that up, we can now make requests with a call that passes in an object and a callback function (The only non-optional field of the object is the 'path' field). But now I want a function to make getting JSON easier, but because I wrote the original function in async fashion, the new one must be also:
Code:
function requestJSON(options, callback) {
// We wrap the passed callback in our own function to parse the data:
request(options, function (error, data) {
var result;
if (error) {
callback(error, null)
} else {
try {
result = JSON.parse(data);
} catch (e) {
error = e;
}
// Notice how the possible errors are continuing down the call stack :D
// This is an odd part of asynchronous programming, but I've noticed this is how
// other modules do it...
callback(error, result);
}
}
}
Now any code that wants a JSON object from a server can get it, and it will be available in the context of the callback function passed to requestJSON:
Code:
requestJSON({path: "/resources/map.json"}, function (error, object) {
// if no error happened, we have the object.
});
This method of programming can be surprisingly intuitive. It's not really limited to JavaScript either, but since all functions are proper objects (which is awesome IMO) it just comes
more naturally. Functions are pretty much the most awesome part of JS.
[Note: I start going off on a tangent here]
Like for instance in the 'request' function above, you can see that I used the 'req' variable in the onload callback for the request, even though that function will only be called after execution has left the scope of the function. I could have used 'this' instead, because it is bound to the XMLHttpRequest, but I was trying to show how functions created maintain a link to the context they were created in. This is an important concept to keep in mind when designing your code.
For instance in the small example of my canvas drawing program, you probably noticed that it looked weird:
Code:
socket.on("drawing", (function () {
var object_To_Hold_Drawing_Commands = Object.create(null);
return function (toDraw) {
// ect...
};
}());
The inner function that is being returned is the one actually called on the "drawing" event. All the data needed converges in that function only, so I wrote what's called a 'closure' that inserts a scope (containing the object that will hold commands) directly in the line of the returned function. No other place has access to that scope, and this allows for encapsulation.
Sorry I just realized I went off on a tangent lol, I'm leaving it in anyway in case you find it helpful in some way .
Originally Posted by
Lesshardtofind
Synchronous behavior can be murderous on the DOM rendering engine pipeline. There are web workers that simulate synchronous threads in JavaScript. The support isn't wide yet, but they can be pretty powerful.
I actually just discovered this earlier today, I've been looking to see if I could get it on the Raspberry, it looks really cool.