# this appears very synchronous
function getPhoto(tag) {
var photoList = syncGet(requestTag(tag));
var photoSizes = syncGet(requestOneFrom(photoList));
return sizesToPhoto(photoSizes);
}
# Two getPhoto() "processes" are spawned. After this,
# the language multiplexes between them via the (single) event loop,
# in a single OS thread.
job1 = spawn getPhoto('tokyo');
job2 = spawn getPhoto('tokyo');
# Wait for both of them to finish. This too happens in an asynchronous
# fashion, i.e. calling job1.join() does not prevent the two jobs from
# running. In effect at this point we have three "processes" running
# (the main process doing the joins, the job1 process and the job2 process).
photo1 = job1.join();
photo2 = job2.join();
drawOnScreen(photo1);
drawOnScreen(photo2);
Yes, I know this may be very hard to implement in Javascript/Node, because it fundamentally changes the way the JS engine needs to work.NOTE: It seems this approach is not new; "green theads" seems to be the right term, and there seem to be a lot of Python-based implementations. Go's goroutines also appear similar (but you can have them run truly in parallel).
BUT note a crucial difference from the "green threads" approach - in my suggested design, there would be no real scheduling. If you perform sequence of operations and they are all guaranteed not to block, this sequence is automatically atomic, and cannot be interrupted by another "process".
I should also mention this programming language I'm developing, called NCD [1], which employs the same idea. See the in-browser demo [2], click on the Spawn example.
Note that NCD implements a unique extension of imperative programming. Statements in general persist even after they have "returned", and they get the chance to do stuff when they are about to be "deinitialized" (see what happens when you click "Request termination" in the Spawn example). Plus, any statement can trigger "backtracking" to its point within the process, causing automatic deinitialization of any statements that follow (try Count example).
Also, IMO promises [3] are just a hack around the fact that the language is not inherently asynchronous. Seriously, who would prefer:
doFoo()
.then(function (foo) {
return doBar(foo);
})
.then(function (bar) {
return doBaz(bar);
})
.then(function(baz) {
console.log(baz);
});
Over this? function myWork () {
foo = doFoo();
bar = doBar(foo);
baz = doBaz(bar);
console.log(baz);
}
spawn myWork();
[1] http://code.google.com/p/badvpn/wiki/NCD
[2] http://badvpn.googlecode.com/svn/wiki/emncd.html
[3] https://gist.github.com/3889970