What are ES7 Async functions? [closed]

邮差的信 提交于 2019-12-12 17:14:15

问题


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?


回答1:


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




回答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.

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



来源:https://stackoverflow.com/questions/35580109/what-are-es7-async-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!