23

Is there any attempt to bring async/await feature from C# 5.0 to any language which can be compiled to JavaScript (such as CoffeScript)? (So it can be used either in web browser or in node.js.)

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
TN.
  • 18,874
  • 30
  • 99
  • 157
  • 2
    In-browser JavaScript and JavaScript via node.js have their own way of doing asynchronous programming. You'll be much better off simply learning how that works and using it as intended instead of trying to force it into a different model (which is likely to be completely impossible anyway). – Pointy Oct 09 '11 at 14:13
  • 9
    @Pointy: C# 5's awaits are a syntactic wrapper around the same callback model. They're **much** easier to use than callbacks, in any language. – SLaks Oct 09 '11 at 14:14
  • OK I of course defer to your broader experience :-) – Pointy Oct 09 '11 at 14:54
  • 1
    @Pointy that's not really true—JS in the browser and JS on NodeJS have fundamentally the *same* programming model, and that is the event loop plus fundamentals such as setTimeout, events, and callbacks. it just so happens that a lot (but not all) of NodeJS's asynchronous functions use callbacks, whereas in the browser it's more events. but that is just a matter of statistics and style. – flow Jun 12 '13 at 14:27
  • @flow I didn't mean that JavaScript in the browser and in Node have their own *distinct* async models; I listed those two environments because there are others (notably Rhino) where there **are** synchronous I/O (etc) operations. – Pointy Jun 14 '13 at 01:09

11 Answers11

17

Async is on feature list for JavaScript harmony. So far there are numerous attempts to provide such functionality in the browser or in node, none of them seem to be compatible with harmony proposal though:

  • Async can be simulated with JS1.7 generators (see task.js). Not yet supported out-of-the-box by V8 (without experimental mode), but works in FF. Possibly traceur or Masacra compiler can be used to bring generators to other environments.
  • There is node-fibers library providing other mechanism for asynchronous programming in node (scarifies performance though). Other attempt basing on v8cgi is described here.
  • Rhino has continuations out of the box providing good alternative. This is why Ringo.js might be worth looking at.
  • Few solutions basing on js2js translation are available, e.g: jscx, NarrativeJS, jwacs, StratifiedJS. Some support integration with node.
  • There are many promise/future libraries trying to solve callbacks problem without extending syntax, however they all suffer from composability issues, i.e. cannot use language constructs like loops across callbacks.
Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
user212328
  • 613
  • 6
  • 7
16

async/await looks to be coming in ECMAScript 7. This proposal was accepted into stage 1 of the specification process in January 2014.

The good news is that Googles traceur compiler already supports it, so you could start using it today.

Sample syntax:

async function asyncValue(value) {
  await timeout(50);
  return value;
}

async/await is also on the TypeScript roadmap.

Brett Postin
  • 11,215
  • 10
  • 60
  • 95
  • Just in case somebody want direct link to draft proposal https://tc39.github.io/ecmascript-asyncawait/ – valerysntx Oct 13 '15 at 14:42
  • 2
    the wait is over with node v7.0.0, well [nearly](https://github.com/nodejs/promises/issues/4#issuecomment-251025934) – mido Oct 27 '16 at 13:14
7

I'm not familiar with C#, but it sounds like what you're looking for is some sort of continuations, so that instead of writing

fs.readFile 'foo.txt', (err, data) ->
  myFunc data

you could instead just write something like

data = &fs.readFile 'foo.txt'  # not a real syntax
myFunc data

This isn't something that JavaScript or CoffeeScript provides. However, there are several other compilers that can do something like this:

  • TameJS - JavaScript-based, mainly just adds this feature
  • Kaffeine - JavaScript-based, adds a bunch of features
  • coco - CoffeeScript-based

See also: List of languages that compile to JavaScript on the CoffeeScript wiki.

Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
  • 1
    Look for "[backcall](https://github.com/satyr/coco/wiki/additions)" on the Coco wiki. It uses a `<-` operator. – Trevor Burnham Oct 09 '11 at 14:52
  • 2
    May I mention that adding such a syntax to javascript has a whole set of negatives, like having to trust the compiled code, having to understand the compiled code, having to debug the compiled code and being tempted to abuse synchronous design patterns in an asynchronous environment. basically they are abstractions that will easily leak unless you know exactly what your doing and I belief only the module author and a small number of people know exactly what they are doing – Raynos Oct 09 '11 at 20:22
5

Yes there is, and you don't even need to compile it, because it is just a simple JavaScript library.

One of my projects called sharpnr.js has the aim to extend JavaScript with great features of C# (and .NET of course) like await/async, or LINQ.

The library is currently in beta, but it's stable and supports almost every statement (for example loops, switch, if), and works well with existing libraries (like jQuery).

The await/async syntax is almost identical to the C# version:

var getAsync = async(function(url) {
  var result = await; $.get(url);
  $("#test").html(result);
});
getAsync("http://www.sharpnrjs.com");

Working example on jsfiddle.

You can download the library from github.

Community
  • 1
  • 1
ajuhos
  • 111
  • 1
  • 6
4

When Node 0.11 (with v8 3.19 [1], which has generators[2]) arrives, you can use Galaxy and code like below.

However, only behind a flag. They are supported natively in ioJS.

function* countLines(path) {
    var names = yield fs.readdir(path);
    var total = 0;
    for (var i = 0; i < names.length; i++) {
        var fullname = path + '/' + names[i];
        if ((yield fs.stat(fullname)).isDirectory()) {
            total += yield countLines(fullname);
        } else {
            var count = (yield fs.readFile(fullname, 'utf8')).split('\n').length;
            console.log(fullname + ': ' + count);
            total += count;
        }
    }
    return total;
}

function* projectLineCounts() {
    var total = 0;
    total += yield countLines(__dirname + '/../examples');
    total += yield countLines(__dirname + '/../lib');
    total += yield countLines(__dirname + '/../test');
    console.log('TOTAL: ' + total);
    return total;
}
Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
3

You can have async/await in Google Chrome with Experimental JS flag enabled, using built-in Generators, Promises and a tiny spawn() function by Jake Archibald:

spawn(function*() { //this function is async
      let story = yield getJSON('story.json'); //yield is like await
      addHtmlToPage(story.heading);
});

Alternatively, you can use:

For browsers not supporting ES6, there is Facebook Regenerator.

niutech
  • 28,923
  • 15
  • 96
  • 106
3

good news,

nodejs supports it from v7.0.0 (well, partially), still need a harmony flag --harmony_async_await, and apparently has some bugs including memory leak, for more details, but there are some concerns as well, and one commentator advises to wait till v8 version 55 which might not be long.

mido
  • 24,198
  • 15
  • 92
  • 117
2

For completeness: I have found that Saltarelle Compiler (which actually compiles C# to JavaScript) also supports await/async.

TN.
  • 18,874
  • 30
  • 99
  • 157
1

Javascript is providing async-await feature with ECMA 7. Now all asynchronous function can be awaited by promisifying them and waiting for promise to resolve. Most of the asynchronous functions like DB calls, API calls, fs and events are returning promise now in Javascript and nodeJs. Now with async-await code is more cleaner, understandable, debugged.

Example

function timeout(){
  return new Promise( resolve => {
    setTimeout(function(){
      resolve(true);
    }, 5000);
  });
}

async function f(){
    let result = await timeout();
}
NAVIN
  • 3,193
  • 4
  • 19
  • 32
1

If you are interested in .NET style asynchronous programming for JavaScript you should look into Rx for JavaScript. Rx for JavaScrpt is Microsoft's JavaScript port of the Reactive Framework. The reactive framework is described as:

A library to compose asynchronous and event-based programs using observable collections and LINQ-style query operators.

You can download Rx for JavaScript here

And you can read more about it, including examples here

You can also install it on node with npm:

npm install rx

It works well with libraries like jQuery, however I am not a CoffeeScript programmer, so I'm not sure what support there is for interoperability with other JavaScript libraries in this language.

dmck
  • 7,801
  • 7
  • 43
  • 79
0

there is https://github.com/loveencounterflow/coffy-script which is the attempt to add yield to CoffeeScript. CoffyScript is very new and as i'm writing this i'm pondering over the difficulties posed by require.extensions being a global, and whether i should be a separate extension. that said, CoffyScript does work, and you will find on my github page numerous examples that show how to write quite succinct asynchronous code using suspend, resume, and yield.

given that yield has arrived in NodeJS 11.2, i believe we should research how to use generators / coroutines to make asynchronous programming more palatable. i for one have tossed out promises, the experience with them having not been so pleasant. Then again, it may take a while before yield becomes available in all major browsers.

flow
  • 3,624
  • 36
  • 48