I'm trying to make (yet another) language that compiles to JavaScript. One of the features I'd like to have is the ability to perform JavaScript's async operations synchronously (not exactly synchronously – without blocking the main thread, of course). Less talk, more examples:
/* These two snippets should do exactly the same thing */
// the js way
var url = 'file.txt';
fetch(url)
.then(function (data) {
data = "(" + data + ")";
return sendToServer(data);
}).then(function (response) {
console.log(response);
});
// synchronous-like way
var url = 'file.txt';
var response = sendToServer("(" + fetch(url) + ")");
console.log(response);
What is the most elegant way to compile it back to JS?
The criteria, sorted by importance:
- Performance
- Backwards compatibility
- Compiled code readability (not really important)
There are several possible ways to implement it, those three came to my mind:
Using Promises:
f(); a( b() );
would turn intof().then(function(){ return b() }).then(function(x){ a(x) });
- pros: relatively simple to implement, polyfillable back to ES3
- cons: creating a new function and a Proxy instance for every function call
-
f(); a( b() );
would turn intoyield f(); tmp = yield b(); yield a( tmp );
- pros: nicer javascript
- cons: creating proxies, generators and iterators on every step, also not polyfillable
- EDIT: in fact they are polyfillable using another recompiler (eg. Regenerator)
Using synchronous XMLHttpRequest:
- request a server script which waits until another call from somewhere else in the code
- pros: de facto no changes in the code, super-easy to implement
- cons: requires server script (=>no portability, browser-only); furthermore, synchronous XMLHttpRequest blocks the thread so it does not work at all
- EDIT: It actually would work inside a Worker
The main problem is that one can't tell if a function is asynchronous until runtime. That results in the two solutions that at least do work being a lot slower than pure JS. So I ask:
Are there any better ways to implement?
From answers:
Await keyword (@MI3Guy)
- C# way (which is good!)
- introduces a new keyword (which can be disguised as a function (1st-class-citizen) that eg. throws if the programmer tries to pass it as an argument)
- How to know that function is asynchronous? No other keywords!
- Every function that contains
await
keyword becomes asynchronous? - When the code gets to
await
, it returns a promise? Else treats as an ordinary function?
- Every function that contains
synchronously (without blocking the thread, of course)
You keep using that word. I do not think it means what you think it means, because synchronously means "blocking the thread".f(); a( b() );
would turn in tof().then(b).then(a);
You don't enclosing functions.