Что такое асинхронные функции ES7?

Я использую Babel уже некоторое время, и мне это нравится. Однако на домашней странице, где перечислены поддерживаемые функции, указано Async functions.

Я много гуглил, и все, что я могу понять, это то, что это функция ES7.

Пожалуйста, что такое асинхронные функции ES7?


person Kizer    schedule 23.02.2016    source источник
comment
Асинхронные функции — ужасная идея, позволяющая отказаться от обещаний и писать асинхронный код построчно, не беспокоясь о том, когда что-то будет сделано и т. д.   -  person adeneo    schedule 23.02.2016
comment
Ужасно? По сути, это ответ на шаблон C# async/await. Заблуждающийся, может быть, ужасный, нет.   -  person Frédéric Hamidi    schedule 23.02.2016
comment
@FrédéricHamidi — к счастью, Javascript — это не C#, и это ужасная идея   -  person adeneo    schedule 23.02.2016
comment
@adeneo, я полагаю, ты не веришь в конвергенцию технологий :)   -  person Frédéric Hamidi    schedule 23.02.2016
comment
@FrédéricHamidi - конечно знаю, но это не значит, что я считаю все изменения хорошими, а это, на мой взгляд, нет.   -  person adeneo    schedule 23.02.2016
comment
Асинхронный поиск ES7 ► Введение в ES7 Async Функции Кажется, это объясняет все, что в нем есть, насколько я понимаю.   -  person Nope    schedule 23.02.2016
comment
Мне на самом деле не интересно знать, хорошая это идея или плохая. Я просто хочу понять концепцию. Я не разработчик C#, поэтому ничего не знаю об асинхронности C#.   -  person Kizer    schedule 23.02.2016
comment
@adeneo: async/await не отказывается от обещаний. Оно охватывает их. Это делает код обещаний со сложным потоком управления намного проще для чтения и записи.   -  person Bergi    schedule 23.02.2016
comment
@Bergi - это просто синтаксический сахар, он позволяет вам вернуть обещание из функции и использовать await для написания кода, как будто он не был асинхронным, построчно. Это упрощает написание, но во многих случаях труднее читать, так как большинство людей привыкли к асинхронным функциям, имеющим обратный вызов, возможность использования и т. д., а теперь вдруг это не так.   -  person adeneo    schedule 23.02.2016
comment
@adeneo: Как и генераторы, он позволяет вам использовать все виды управляющих структур с промисами, которые вы вряд ли могли использовать раньше. И async функции по-прежнему доступны, каждая из них возвращает обещание! Их можно полностью прозрачно заменить обычными функциями, возвращающими промисы, подобно тому, как функции-генераторы можно заменять функциями, возвращающими итераторы (единственное отличие — .toString()).   -  person Bergi    schedule 23.02.2016


Ответы (2)


Async Await работает с обещаниями ES6. Вы можете думать о них как о способе написания синхронного кода с промисами.

Ключевое слово async помечает как метод, который будет выполнять асинхронный вызов. Ключевое слово await отмечает фактический вызов.

С обещанием вам нужно передать метод методу .then() обещания для обработки результата.

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

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

Это все работает нормально. С Async/Await мы можем написать последнюю функцию немного по-другому.

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

Преимущество этого заключается в том, что он просто уменьшает потребность в обратных вызовах.

Подробнее см.: https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html

person Martin    schedule 23.02.2016
comment
Пожалуйста, оставьте комментарий, когда вы голосуете против. Также дайте мне знать, если вы голосуете против, потому что вам не нравится концепция async/await? - person Martin; 23.02.2016
comment
К вашему сведению, обещания являются частью ES6 (ES2015), а async/await не будет частью ES7 (ES2016). - person Felix Kling; 23.02.2016
comment
Спасибо за этот пример. Я наконец понял, что async сам по себе не делает функцию асинхронной. Это нужно сделать с помощью Promise. async только помечает некоторую функцию как способную использовать await и делает вызов функции асинхронной функции синхронным. - person Ryan H.; 13.02.2017

< strong>ES2016 (обычно именуемый ES7 или ECMAScript 7) — это следующая эволюция стандарта ECMA-262 (обычно называемого JavaScript), и он все еще находится на ранней стадии.

Асинхронные функции — это новая функция JavaScript, предложенная как часть стандарта ES2016 и пока не поддерживаемая ни одним браузером. Они построены на основе обещаний.

См. ниже введение в эту новую функцию из различных авторитетных источников.

Примечание :

Несмотря на то, что асинхронные функции обычно обозначаются как ES7 asynch functions (например, чтобы отличить их от async.js или асинхронный JavaScript в целом), Аксель Раушмайер< /a> рекомендует не называть их так, однако как функция будет включена в следующий стандарт только после того, как его предложение достигнет стадии 4.

Асинхронные функции сейчас только на третьем этапе. Фактически, ES2016, скорее всего, не будет содержать асинхронных функций (поскольку < a href="https://stackoverflow.com/users/218196/felix-kling">Феликс Клинг указал в комментариях ниже).


Из предложения этапа 3:

Введение

Введение промисов и генераторов в ECMAScript дает возможность значительно улучшить модель на уровне языка для написания асинхронного кода в ECMAScript.

Аналогичное предложение было сделано для отложенных функций во время обсуждения ES6. Предложение здесь поддерживает те же варианты использования, используя аналогичный или тот же синтаксис, но напрямую опираясь на структуры потока управления, параллельные структурам генераторов, и используя промисы для возвращаемого типа вместо определения пользовательских механизмов.

Разработка этого предложения происходит по адресу https://github.com/tc39/ecmascript-asyncawait< /сильный>. Пожалуйста, регистрируйте проблемы там. Нетривиальные вклады ограничены членами TC39, но запросы на вытягивание для незначительных проблем приветствуются и поощряются!

Статус этого предложения

Это предложение было принято на этапе 3 ("Кандидат") процесса спецификации в сентябре 2015 года. Чемпион намерен принять это предложение на этапе 4 («Завершено») к концу ноября.

Примеры

Возьмем следующий пример, сначала написанный с использованием промисов. Этот код связывает набор анимаций с элементом, останавливаясь при возникновении исключения в анимации и возвращая значение, созданное окончательной успешно выполненной анимацией.

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;
    });
}

Уже с промисами код значительно улучшился по сравнению с прямым стилем обратного вызова, где такого рода зацикливание и обработка исключений сложны.

Task.js и подобные библиотеки предлагают способ использования генераторов для дальнейшего упрощения поддержки кода. Такое же значение:

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;
    });
}

Это заметное улучшение. Все шаблонные обещания, выходящие за пределы семантического содержания кода, удаляются, а тело внутренней функции представляет собой намерение пользователя. Тем не менее, есть внешний слой шаблона, чтобы обернуть код в дополнительную функцию генератора и передать его в библиотеку для преобразования в промис. Этот уровень необходимо повторять в каждой функции, использующей этот механизм для создания обещания. Это настолько распространено в типичном асинхронном коде Javascript, что имеет смысл избавиться от необходимости в оставшемся шаблоне.

С асинхронными функциями весь оставшийся шаблон удаляется, оставляя в тексте программы только семантически значимый код:

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;
}

Из статьи Джейка Арчибальда асинхронные функции ES7 :

Асинхронно с промисами

В статье HTML5Rocks о обещаниях , в последнем примере показано, как загрузить некоторые данные JSON для истории, затем использовать их для получения дополнительных данных JSON для глав, а затем отобразить главы по порядку, как только они будут получены.

Код выглядит следующим образом:

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';
    });
}

Не плохо, но…

На этот раз с асинхронными функциями ES7…

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';
}

С помощью асинхронных функций (полное предложение) вы можете await на обещать. Это останавливает функцию неблокирующим образом, ждет разрешения обещания и возвращает значение. Если обещание отклонено, оно выдает значение отклонения, поэтому вы можете справиться с этим, используя catch.

Изменить: изначально я использовал await в функции стрелки, очевидно, это не так разрешено, поэтому я заменил его циклом for. Доменик рассказал мне, почему await нельзя использовать в стрелочные функции.

loadStory возвращает обещание, поэтому вы можете использовать его в других асинхронных функциях.

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

Из статьи KoaJS Эволюция асинхронного JavaScript :

Генераторы / выход

Генераторы JavaScript — относительно новая концепция, они были представлены в ES6 (также известном как ES2015).

Было бы неплохо, если бы при выполнении функции можно было приостановить ее в любой момент, вычислить что-то еще, сделать что-то еще, а затем вернуться к ней, даже с некоторым значением, и продолжить?

Это именно то, что функции генератора делают для вас. Когда мы вызываем функцию генератора, она не запускается, нам придется перебирать ее вручную.

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 }

Если вы хотите легко использовать генераторы для написания асинхронного JavaScript, вам понадобится co< /а> тоже.

Co — это средство управления потоком управления на основе генератора для Node.js и браузера, использующее промисы и позволяющее красиво писать неблокирующий код.

С co наши предыдущие примеры могут выглядеть примерно так:

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

Вы можете спросить: а как насчет операций, выполняемых параллельно? Ответ проще, чем вы думаете (на самом деле это просто Promise.all):

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

Асинхронный / ожидающий

Асинхронные функции были представлены в ES7 и в настоящее время доступны только с использованием транспилятора, такого как babel. (отказ от ответственности: сейчас мы говорим о ключевом слове async, а не о пакете async)

Короче говоря, с ключевым словом async мы можем делать то же, что и с комбинацией co и генераторов, кроме взлома.

введите здесь описание изображения

Под капотом функции async используют промисы — вот почему асинхронная функция вернется с ошибкой Promise.

person John Slegers    schedule 23.02.2016
comment
Почему этот ответ получает отрицательные голоса ?! - person John Slegers; 23.02.2016
comment
Мои два цента: я думал об этом несколько минут и в итоге проголосовал за него, потому что это совокупность выдержек из разных источников, практически без оригинального содержания. Я признаю усилия, которые вы вложили в форматирование, но я все еще не думаю, что мы должны это поощрять. - person Frédéric Hamidi; 23.02.2016
comment
@FrédéricHamidi : Спасибо за отзыв! Однако то, что вы говорите, противоречит моему личному опыту. Некоторые из ответов с самым высоким рейтингом, которые я видел на этом сайте, являются просто выдержками из авторитетных источников со ссылками на источники. Черт возьми, второй по количеству голосов ответ из всех 281 ответов, которые я разместил на StackOverflow, — это всего два исключения из авторитетных источников. Итак, по моему опыту, именно эти ответы пользователи ТАК ценят больше всего. - person John Slegers; 23.02.2016
comment
Сколько лет этим ответам? То, что представляет собой подходящий ответ, имеет тенденцию меняться со временем здесь. В любом случае, если ваше последнее предложение верно, то ваш ответ должен быть очень быстро возвращен в форму. - person Frédéric Hamidi; 23.02.2016
comment
@FrédéricHamidi: Хороший вопрос. Время покажет! И еще раз спасибо за отзыв! - person John Slegers; 23.02.2016
comment
К вашему сведению, async/await не будет частью ES7 (ES2016). Только предложения стадии 4. - person Felix Kling; 23.02.2016
comment
@FelixKling: Согласно проекту этапа 3, ожидается, что предложение будет принято на этапе 4 к концу ноября 2016 года. Не будет ли слишком поздно? Если да, то знаете ли вы какие-либо источники, которые могут это подтвердить? - person John Slegers; 23.02.2016
comment
@JohnSlegers: Да, ES2016 будет выпущен примерно в июне. См. также twitter.com/bterlson/status/692489384654999552 . - person Felix Kling; 23.02.2016
comment
@JohnSlegers: И twitter.com/bterlson/status/692424625813377026: все, что этап 4 к четвергу пройдет, да.. И tc39.github.io/process-document - person Felix Kling; 23.02.2016
comment
@FelixKling: Спасибо за это! Я добавил примечание к своему ответу, чтобы отразить точку зрения, высказанную в ваших комментариях, наряду с различными незначительными улучшениями, связанными с наименованием будущего стандарта Ecmascript. - person John Slegers; 23.02.2016