Почему в ES2017 вводится async/await, когда в ES6 уже есть генераторы?

Читая о async и await, я заметил, что это почти эквивалент функций-генераторов. Обратите внимание на этот фрагмент из TypeScript Deep Dive:

Асинхронное ожидание

(...)

// Not actual code. A thought experiment
async function foo() {
    try {
        var val = await getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
}

(...)

Сгенерированный JavaScript

Вам не обязательно это понимать, но это довольно просто, если вы читали о генераторах. Функцию foo можно просто обернуть следующим образом:

const foo = wrapToReturnPromise(function* () {
    try {
        var val = yield getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
});

где wrapToReturnPromise просто выполняет функцию генератора, чтобы получить generator, а затем использовать generator.next(), если значение равно promise, это будет then+catch обещание и в зависимости от результата вызывает genertor.next(result) или genertor.throw(error). Вот и все!

В чем причина того, что это оказалось «новой функцией»? ИМХО, просто использовать эту функцию wrapToReturnPromise из какой-нибудь библиотеки было бы так же хорошо, не усложняя при этом сам JavaScript.

Примечание: это связано с этим вопросом, но здесь я спрашиваю о "почему", а не "как". Я пытаюсь понять мотивы.


person mik01aj    schedule 01.03.2017    source источник
comment
wrapToReturnPromise сложен (и часто реализуется неправильно/слишком наивно) и влечет за собой больше накладных расходов, чем необходимо. async function с await может лучше анализироваться и оптимизироваться движком.   -  person Bergi    schedule 01.03.2017
comment
Настоящая сила заключается в наличии обоих: асинхронного генератора функции. Это просто невозможно только с синтаксисом генератора.   -  person Bergi    schedule 01.03.2017
comment
async/await не является частью ES7 (ES2016)! Это будет частью выпуска этого года, ES2017.   -  person Felix Kling    schedule 07.03.2017


Ответы (1)


На первый взгляд, синтаксис похож, и вы можете предположить, что код будет вести себя аналогично, но есть некоторые ключевые отличия:

  • Говорите, что вы имеете в виду: function* и yield означают что-то очень отличное от async function и await, аналогично тому, как Subclass.prototype = Object.create(Superclass.prototype); Subclass.prototype.constructor = Subclass отличается от class Subclass extends Superclass

  • Приоритет оператора: вы можете использовать await a + await b для обозначения (await a) + (await b), но yield a + yield b означает yield (a + (yield b))

  • Дальнейшее развитие: async/await подготовить почву для действительно интересной работы с оптимистичной блокировкой транзакций и спекулятивным выполнением, поскольку они (как отмечалось в этой ветке) являются явными маркерами границ атомарности.

  • Другие аргументы. Существует также множество контраргументов против async/await -- включая многих людей, которые говорят, что генераторы просто "лучше" и что async/await движется в неправильном направлении.

Совершенно резюмировано с сайта обсуждения ES . Я рекомендую вам прочитать всю ветку, так как в ней есть очень интересные обсуждения на эту тему.

person Dan Esparza    schedule 01.03.2017