As a beginner in Javascript, i was quite in shock to find out that there isn't any "wait" mechanism in javascript (i'm not considering timeout, you'll see why in a second), and if i want to deal with an asynchronous command i needed to use a callback. Pay attention to the fact that i put the wait in quotes, its because JS can't really wait, I just can't find a better word.
the mechanism of callbacks quickly turned for me to a chain of ugly callbacks that made my code much harder to read.
the problem begin when you have to force a synchronous order on a sequence of asynchronous command (those that ask for a callback), for example ajax commands.
consider this example:
1. here is what i considered a nice function:
function foo(){
var result = "error";
var key=getKey();
if(verify(key)){
var name=getName();
if (verify(name)) {
login(key,name);
result = "ok";
}
}
return result;
}
2. now what if getKey and getName needed a callback and getName have to be called only after we acquire the key?? this function should be broke into this:
function foo(){
getKey(callback);
}
function callback(key){
if verify(key){
getName(callback2);
}
function callback2(name){
if verify(name){
return "ok";
}
}
you see how this simple "nice" method becomes ugly when callbacks are needed? and what if you have 20 or so functions that needed to be called sequentially and not only two?
you will need to write 20 functions and chain them with the callbacks...sweet mother of ugliness.
3.here is the same function, but lets say that we could introduce a new syntax that will do exactly the same as in (2), but will look like this:
when the interpreter sees the "wait" word, some magic will happen behind the scenes to create the exact same effect as the code in (2):
function foo(){
var result = "error";
wait var key=getKey();
if(verify(key)){
wait var name=getName();
if (verify(name)) {
login(key,name);
result = "ok";
}
}
return result;
}
this is how things look like in most other languages, but as we already know, in JavaScript it is more problematic because JavaScript is a single threaded language.
there are some smart way to work around things like using a "state machine like" mechanism and Promises...but none of them is as simple as just waiting for the asynchronous call to return.
another way to work around things is to build a tool, just like the tools that format your code, that could take a code written in the format of (3) and produce a code that looks like (2). building this tool is actually quite easy.
and now for my question:
instead of building an external tool to do the work, why not just teaching the JS interpreter to do the work??
why not using the already existing mechanism of closure to introduce a new "wait" feature into javascript??
what i mean is that if you'll think about it, all we need to do is to inroduce a new syntax that will cause the javascript interpreter to use the next line as the handler for the current asynchronous call, just like "function" label tells the interpreter to consider the next line as the body of a function (not exactly, but you know what i mean). like this:
function foo(){
wait bar=doSomethingAsnyc(value);
doNextAsyncCommend(bar);
}
so my questions:
1. what do you think about this proposal?
2. is it possible to implement it using only existing mechanism of the current js interpreter features?
let me clarify just one thing:
I'm not suggesting to make JS a multi-threaded language or something fancy..actually i don't want to change anything in the inner-working of JS. I'm trying to suggest a syntactic sugar only and i want to understand if it is possible to introduce it using only existing mechanisms.
I have an incomplete proposal on how to do this and i hope that with your help we could actually bring this proposal into a practical way to implement a wait mechanism without breaking any existing standard, and who knows, maybe we could be able to introduce the new mechanism into FireFox and actually make a change.
I don't know how JavaScript interpreters implement the stack but i can imagine a theoretical implementation (that sadly needs to introduce new features to the interpreter) like this:
1. when you see the word "wait" in the beginning of the line, run the command (in our example the call to doSomethingAsnyc(value)) but Behind the scenes, pass within the call a fake callable object so that we will not break any existing syntax while the asynchronous function will try to send back the results using: callback(result);
this fake callable will actually save the result on top of the stack when it will be ready.
2. when you get to the next line of code, save a pointer (more like a marker) to the current position in the stack(+1 to save space for the return value of the call). leave the function scope and continue to run.
3. when the fake callable object that we have passed within the call is being called (meaning that the asynchronous call is completed), jump the stack pointer to the marker and save the return value on top of the stack.
4. pop the return value into the variable that was after the wait (the "bar"), and continue to run until the end of the function scope.
5. when reaching the end of the function scope, use the same mechanism that already exist in js to finish handling of an event and continue from the same spot where we left.
so, what do you think??
UPDEATE2:
after a very long discussion in the comments i see that both of the professional users that tried to answer my question did not understand me right.
I don't know how to explain things better and the English is doing me a hard time, so please, if someone got my proposal right please try to explain to others what it is about. just put it as an answer and ill update my question with your explanation.