augmented
v0.4.0
Published
A javascript preprocessor
Downloads
4
Readme
Augmented JavaScript
Augmented javascript is a javascript-preprocessor written in javascript. It's function is similar to the more known javascript preprocessor CoffeScript, however, while CoffeScript has more or less invented a new language alltogether, Augmented JavaScript is a lot more similar to plain old JavaScript.
Currently Augmented JavaScript adds 3 new features to the JavaScript language. All of these features are new, and not very well tested, so bugs should be expected. These new features are:
- Await
- Yield
- For..Of-Loops
Await
The await
-keyword is taken from the newer versions of C# and VB.NET.
It's job is to pause the execution of a piece of code untill new data is availible,
and then continue off where it left.
This results in the ability to write async functions very easily without the need for callback-nesting.
For instance, let's asume we have a "magic" function called load
whos task it is to
perform a simple xhr-request and callback when the data is availible.
Using regular javascript one would in general write code such as this:
function login(username, password, cb) {
getUser(username, password, function(user) {
getGroups(user.id, function(groups) {
cb({
user: user,
groups: groups
});
});
});
}
function getUser(username, password, cb) {
load('/getUser', {
username: username,
password: password
}, function(data) {
if(data.success) {
cb(data.user);
} else {
cb(null);
}
});
}
function getGroups(userId, cb) {
load('/getGroups/' + userId, function(data) {
if(data.success) {
cb(data.groups);
} else {
cb(null);
}
});
}
As you can see, there's a lot of nesting of functions, and it's not always
easy to understand what is going to happen and in what order. People who are
unused with javascript typically expect that when you've run the login-function,
the user will be logged in immidiately, which isn't the case because our load
-function
is async. Now, take a look at the same code rewritten to use Augmented JavaScript
(here ofcause I assume that the load-function has been written in such a way that
it is usable with the await-keyword and not just callbacks as in the previous
example, more on that later).
function login(username, password) {
var user = await getUser(username, password);
var groups = await getGroups(user.id);
return {
user: user,
groups: groups
};
}
function getUser(username, password) {
var data = await load('/getUser', {
username: username,
password: password
});
if(data.success) {
return data.user;
} else {
return null;
}
}
function getGroups(userId) {
var data = await load('/getGroups' + userId);
if(data.success) {
return data.groups;
} else {
return null;
}
}
Quite a bit easier to read, no? The result of these two snippets of code should theoretically be the same. However, as said, the probability of experiencing bugs in Augmented JavaScript is still fairly high, and I have not explicitly tested the snippets found here yet.
What is awaitable
Internally, Augmented JavaScript uses the exelent Q-library to handle waiting. That means that anything that can be understood by the Q-library, can be waited for.
Yield
The second new feature is the yield
-keyword. The yield-keyword works in certain ways
almost like the await
keyword, with the exception that instead of waiting for
whatever you pass after the yield
-keyword it is returned to the calling function.
The yield
-keyword is simply put used to create generators (or iterators). A simple
example illustrates best how it works:
function testGenerator() {
yield 1;
yield 2;
yield 3;
}
function runTest() {
var iter = testGenerator();
console.log(iter.next()); // outputs 1
console.log(iter.next()); // outputs 2
console.log(iter.next()); // outputs 3
console.log(iter.next()); // throws StopIteration
}
Using yield
you can easily create functions that have no end, because only the data you
request is generated. For instance, one can create a simple fibionacci-generator like this:
function fib() {
var a = 1, b = 0;
while(true) {
yield a;
b = a + b;
yield b;
a = a + b;
}
}
For..Of-Loops
The for..of
-loop only works on iterators or objects that have the same signature.
Use for..of
to loop though all the values generated from a generator. For instance,
if you take the function runTest
created in the previous section, you could
rewrite the code to this using for..of
:
function runTest() {
for(var n of testGenerator())
console.log(n);
}
break
and continue
works as one would expect, so to print all the fib-numbers less than 100
you could do this:
function printFib() {
for(var n of fib()) {
if(n > 100) break;
console.log(n);
}
}