1

I have been using Babel for a while now, and I am loving it. However, on the home page, where it lists the supported features, it says Async functions.

I have done a lot of Googling, and all I can seem to understand is that it's an ES7 feature.

Please what are ES7 Async functions?

John Slegers
  • 45,213
  • 22
  • 199
  • 169
Kizer
  • 1,548
  • 2
  • 14
  • 24
  • Async functions are a horrible idea, letting you forgo promises and write asynchronous code line by line, without worrying about when things are done etc. – adeneo Feb 23 '16 at 14:27
  • *Horrible?* It's basically the answer to C#'s `async`/`await` pattern. Misguided, maybe, horrible, no. – Frédéric Hamidi Feb 23 '16 at 14:28
  • @FrédéricHamidi - Javascript isn't C#, luckily, and it's a *horrible* idea – adeneo Feb 23 '16 at 14:29
  • @adeneo, I assume you don't believe in convergence in technology, then :) – Frédéric Hamidi Feb 23 '16 at 14:30
  • 1
    @FrédéricHamidi - of course I do, but that doesn't mean I think all change is good, and this, in my opinion, isn't. – adeneo Feb 23 '16 at 14:31
  • 2
    "ES7 Async" search ► [A Primer on ES7 Async Functions](http://code.tutsplus.com/tutorials/a-primer-on-es7-async-functions--cms-22367) It seems to explain everything there is to it as far as I can see. – Nope Feb 23 '16 at 14:34
  • I am not really interested in knowing if it's a good or bad idea. I just want to understand the concept. I am not a C# developer, so I don't know anything about C# async. – Kizer Feb 23 '16 at 14:48
  • 2
    @adeneo: `async`/`await` does not forgo promises. It embraces them. It makes promise code with complex control flow a lot easier to read and write. – Bergi Feb 23 '16 at 16:06
  • @Bergi - it's just syntactic sugar, it lets you return a promise from a function, and use `await` to write code like it wasn't async, line by line. It makes it easier to write, but in many cases harder to read, as most people are used to asynchronous functions having a callback, being thenable etc. and now suddenly, it isn't. – adeneo Feb 23 '16 at 17:09
  • 1
    @adeneo: [Like generators](http://stackoverflow.com/q/23613612/1048572), it empowers you to use all kinds of control structures with promises that you could hardly use before. And `async` functions are still thenable, every of them returns a promise! They are totally transparently exchangeable with normal promise-returning functions, like generator functions are exchangeable with iterator-returning functions (the only difference being `.toString()`). – Bergi Feb 23 '16 at 17:26

2 Answers2

5

Async Await work with ES6 Promises. You can think of them as a way to write synchronous like code with Promises.

The async keyword marks as method that will make an asynchronous call. The await keyword marks the actual call.

With a promise you need to pass a method to the .then() method of the promise to to handle the result.

function doSomethingAsync() {
    return new Promise((resolve, reject) => {
        // call Rest service and resolve here
    })
}

function printResult() {
    doSomethingAsync()
        .then(result => console.log(result));
}

This all works fine. With Async/Await we can write the last function a little different.

async function printResult() {
    let result = await doSomethingAsync();
    console.log(result);
}

The benefit of this is it simply reduces the need for callbacks.

For more see: https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html

Martin
  • 15,820
  • 4
  • 47
  • 56
  • Please leave a comment when you down vote. Also let me know if you are downvoting because you don't like the concept of async/await? – Martin Feb 23 '16 at 15:52
  • 1
    FYI, Promises are part of ES6 (ES2015) and `async/await` is **not** going to be part of ES7(ES2016). – Felix Kling Feb 23 '16 at 16:13
  • Thanks for this example. I finally realized that `async` by itself is not to make a function asynchronous. That needs to be done using a `Promise`. `async` only marks some function as being able to use `await` and makes the function call to the async func appear synchronous-ish. – Ryan H. Feb 13 '17 at 20:47
2

ES2016 (commonly refered to as ES7 or ECMAScript 7) is the next evolution of the ECMA-262 standard (commonly referred to as JavaScript), and still at an early stage.

Async functions are a new JavaScript feature, proposed as a part of the ES2016 standard and not yet supported by any browsers. They're built on top of promises.

See below for an introduction to this new feature from various authoritative sources.

Note :

Even though Async functions are commonly refered to as ES7 asynch functions (eg. to disambiguate them from async.js or asynchronous JavaScript in general), Axel Rauschmayer recommends not calling them that, though, as a feature will only be included in the next standard once its proposal has reached stage 4.

Async functions are only at stage 3 right now. In fact, ES2016 will likely not contain async functions (as Felix Kling pointed out in the comments below).


From the stage 3 proposal :

Introduction

The introduction of promises and generators in ECMAScript presents an opportunity to dramatically improve the language-level model for writing asynchronous code in ECMAScript.

A similar proposal was made with Deferred Functions during ES6 discussions. The proposal here supports the same use cases, using similar or the same syntax, but directly building upon control flow structures parallel to those of generators, and using promises for the return type, instead of defining custom mechanisms.

Development of this proposal is happening at https://github.com/tc39/ecmascript-asyncawait. Please file issues there. Non-trivial contributions are limited to TC39 members but pull requests for minor issues are welcome and encouraged!

Status of this proposal

This proposal was accepted into Stage 3 ("Candidate") of the ECMAScript spec process in September 2015. The champion intends for this proposal to be accepted into Stage 4 ("Finished") by the end of November.

Examples

Take the following example, first written using Promises. This code chains a set of animations on an element, stopping when there is an exception in an animation, and returning the value produced by the final succesfully executed animation.

function chainAnimationsPromise(elem, animations) {
    let ret = null;
    let p = currentPromise;
    for(const anim of animations) {
        p = p.then(function(val) {
            ret = val;
            return anim(elem);
        })
    }
    return p.catch(function(e) {
        /* ignore and keep going */
    }).then(function() {
        return ret;
    });
}

Already with promises, the code is much improved from a straight callback style, where this sort of looping and exception handling is challenging.

Task.js and similar libraries offer a way to use generators to further simplify the code maintaining the same meaning:

function chainAnimationsGenerator(elem, animations) {
    return spawn(function*() {
        let ret = null;
        try {
            for(const anim of animations) {
                ret = yield anim(elem);
            }
        } catch(e) { /* ignore and keep going */ }
        return ret;
    });
}

This is a marked improvement. All of the promise boilerplate above and beyond the semantic content of the code is removed, and the body of the inner function represents user intent. However, there is an outer layer of boilerplate to wrap the code in an additional generator function and pass it to a library to convert to a promise. This layer needs to be repeated in every function that uses this mechanism to produce a promise. This is so common in typical async Javascript code, that there is value in removing the need for the remaining boilerplate.

With async functions, all the remaining boilerplate is removed, leaving only the semantically meaningful code in the program text:

async function chainAnimationsAsync(elem, animations) {
    let ret = null;
    try {
        for(const anim of animations) {
            ret = await anim(elem);
        }
    } catch(e) { /* ignore and keep going */ }
    return ret;
}

From Jake Archibald's article ES7 async functions :

Async with promises

In the HTML5Rocks article on promises, the final example show how you'd load some JSON data for a story, then use that to fetch more JSON data for the chapters, then render the chapters in order as soon as they arrived.

The code looks like this:

function loadStory() {
    return getJSON('story.json').then(function(story) {
        addHtmlToPage(story.heading);

        return story.chapterURLs.map(getJSON)
            .reduce(function(chain, chapterPromise) {
            return chain.then(function() {
                return chapterPromise;
            }).then(function(chapter) {
                addHtmlToPage(chapter.html);
            });
        }, Promise.resolve());
    }).then(function() {
        addTextToPage("All done");
    }).catch(function(err) {
        addTextToPage("Argh, broken: " + err.message);
    }).then(function() {
        document.querySelector('.spinner').style.display = 'none';
    });
}

Not bad, but…

This time with ES7 async functions…

async function loadStory() {
    try {
        let story = await getJSON('story.json');
        addHtmlToPage(story.heading);
        for (let chapter of story.chapterURLs.map(getJSON)) {
            addHtmlToPage((await chapter).html);
        }
        addTextToPage("All done");
    } catch (err) {
        addTextToPage("Argh, broken: " + err.message);
    }
    document.querySelector('.spinner').style.display = 'none';
}

With async functions (full proposal), you can await on a promise. This halts the function in a non-blocking way, waits for the promise to resolve & returns the value. If the promise rejects, it throws with the rejection value, so you can deal with it using catch.

Edit: I originally used await within an arrow function, apparently that's not allowed so I've replaced it with a for loop. Domenic gave me a knowledge smack-down on why await can't be used in arrow functions.

loadStory returns a promise, so you can use it in other async functions.

(async function() {
    await loadStory();
    console.log("Yey, story successfully loaded!");
}());

From KoaJS article The Evolution of Asynchronous JavaScript :

Generators / yield

JavaScript Generators is a relatively new concept, they were introduced in ES6 (also known as ES2015).

Wouldn't it be nice, that when you execute your function, you could pause it at any point, calculate something else, do other things, and then return to it, even with some value and continue?

This is exactly what generator functions do for you. When we call a generator function it doesn't start running, we will have to iterate through it manually.

function* foo () {  
    var index = 0;
    while (index < 2) {
        yield index++;
    }
}
var bar =  foo();

console.log(bar.next());    // { value: 0, done: false }  
console.log(bar.next());    // { value: 1, done: false }  
console.log(bar.next());    // { value: undefined, done: true }

If you want to use generators easily for writing asynchronous JavaScript, you will need co as well.

Co is a generator based control flow goodness for Node.js and the browser, using promises, letting you write non-blocking code in a nice-ish way.

With co, our previous examples may look something like this:

co(function* (){  
    yield Something.save();
}).then(function() {
    // success
})
.catch(function(err) {
    //error handling
});

You may ask: what about operations running in parallel? The answer is simpler than you may think (under the hoods it is just a Promise.all):

yield [Something.save(), Otherthing.save()];

Async / await

Async functions were introduced in ES7 - and currently only available using a transpiler like babel. (disclaimer: now we are talking about the async keyword, not the async package)

In short, with the async keyword we can do what we are doing with the combination of co and generators - except the hacking.

enter image description here

Under the hood async functions using Promises - this is why the async function will return with a Promise.

Community
  • 1
  • 1
John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • Why is this answer getting downvotes?! – John Slegers Feb 23 '16 at 15:43
  • 4
    My two cents: I thought about it for a few minutes, and I ended up downvoting it because it is an aggregate of excerpts from different sources, with little to no original content. I recognize the efforts you put into formatting, but I still don't think we should encourage this. – Frédéric Hamidi Feb 23 '16 at 15:51
  • @FrédéricHamidi : **Thanks for your feedback!** What you're saying is in contradiction with my personal experience, though. Some of the highest rated answers I've seen on this website are just excerpts from authoritative sources with source references. Heck, the second most upvoted answer out of all the 281 answers I've put on StackOverflow so far is just two excepts from authoritative sources. So, in my experience, these are actually the answers SO users appreciate the most. – John Slegers Feb 23 '16 at 15:55
  • How old are these answers? What constitutes an appropriate answer tends to change with time here. Anyway, if your last sentence is true, then your answer should be upvoted back into shape very quickly. – Frédéric Hamidi Feb 23 '16 at 15:57
  • 1
    @FrédéricHamidi : Good point. Time will tell! And again, thanks for your feeback! – John Slegers Feb 23 '16 at 16:00
  • 1
    FYI, `async/await` is **not** going to be part of ES7 (ES2016). Only stage 4 proposals are. – Felix Kling Feb 23 '16 at 16:12
  • @FelixKling : According to the Stage 3 draft, the proposal is expected to be accepted into Stage 4 by the end of November 2016. Will that be too late? If yes, do you know of any sources that can confirm that? – John Slegers Feb 23 '16 at 16:16
  • @JohnSlegers: Yes, ES2016 is going to be released around June I guess. See also https://twitter.com/bterlson/status/692489384654999552 . – Felix Kling Feb 23 '16 at 16:17
  • @JohnSlegers: And https://twitter.com/bterlson/status/692424625813377026: *"Any that are stage 4 by Thursday will make it in, yes."*. And https://tc39.github.io/process-document/ – Felix Kling Feb 23 '16 at 16:24
  • 1
    @FelixKling : **Thanks for that!** I added a note to my answer to reflect the point made in your comments, along with various minor improvements involving the naming of the upcoming Ecmascript standard. – John Slegers Feb 23 '16 at 16:38