В чем разница между обещаниями JavaScript и async await?


103

Я уже использую функции ECMAScript 6 и ECMAScript 7 (благодаря Babel) в своих приложениях - как мобильных, так и веб-.

Первым шагом, очевидно, был уровень ECMAScript 6. Я изучил множество асинхронных шаблонов, обещаний (которые действительно многообещающие), генераторов (не знаю, почему используется символ *) и т. Д. Из них обещания очень хорошо подходят для моей цели. И я довольно часто использую их в своих приложениях.

Вот пример / псевдокод того, как я реализовал базовое обещание -

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

Шло время, я наткнулся на ECMAScript 7 признаков, и один из них ASYNCи AWAITключевых слов / функции. Все это вместе творит великие чудеса. Я начал заменять некоторые из своих обещаний на async & await. Кажется, они добавляют большую ценность стилю программирования.

Опять же, вот псевдокод того, как выглядит моя функция async, await:

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

Не говоря уже о синтаксических ошибках (если таковые имеются), они оба делают то же самое, что я чувствую. Мне почти удалось заменить большинство своих обещаний на async, awaits.

Почему требуется async, await, когда обещания выполняют аналогичную работу?

Решает ли async, await более серьезную проблему? Или это было просто другое решение проблемы обратного вызова?

Как я сказал ранее, я могу использовать обещания и async, ждать решения той же проблемы. Есть ли что-то конкретное, что async await решено?

Дополнительные примечания:

Я широко использую async, awaits и promises в своих проектах React и модулях Node.js. React особенно был ранней пташкой и принял множество функций ECMAScript 6 и ECMAScript 7.


3
Ваш первый блок кода, похоже, использует обещание для синхронной операции. Почему ты бы так поступил? Синхронный, по своей природе, легче писать код, поэтому не должно быть особых причин для того, чтобы обернуть синхронную операцию в обещание и заставить ее теперь быть асинхронной.
jfriend00

@ jfriend00 Да, вы правы. Отредактировал код. Спасибо.
bozzmob

2
Вы все еще пытаетесь использовать инструменты async с синхронными функциями - теперь в обоих блоках кода. Зачем?
jfriend00

@ jfriend00 Хорошо. Вот мой код gist.github.com/bozzmob/26d38b83dc37d1be37f5 . Подскажите, пожалуйста, что я делаю не так?
bozzmob

10
Похоже, вам просто нужно много прочитать, чтобы понять, для чего нужны async и await. Вот несколько статей: Долгий путь к Async / Await в JavaScript и Упрощение асинхронного кодирования с помощью асинхронных функций ES7 и Укрощение асинхронного зверя с помощью ES7 .
jfriend00

Ответы:


82

Почему требуется async, await, когда Promises выполняет аналогичную работу? Решает ли async, await более серьезную проблему?

async/awaitпросто дает вам ощущение синхронности в асинхронном коде. Это очень элегантная форма синтаксического сахара.

Для простых запросов и манипулирования данными обещания могут быть простыми, но если вы столкнетесь со сценариями, в которых есть сложные манипуляции с данными и многое другое, легче понять, что происходит, если код просто выглядит так, как будто он синхронный (иными словами, синтаксис сам по себе является формой «случайной сложности», которую async/awaitможно обойти).

Если вам интересно знать, вы можете использовать такую ​​библиотеку co(наряду с генераторами), чтобы создать такое же ощущение. Подобные вещи были разработаны для решения проблемы, которая в async/awaitконечном итоге решает (изначально).


Не могли бы вы пояснить, что означает «случайная сложность»? Кроме того, когда дело доходит до производительности, нет никакой разницы между ними?
bozzmob

@bozzmob, shaffner.us/cs/papers/tarpit.pdf <- он объясняет там «случайную сложность». Что касается вашего вопроса о производительности, я сомневаюсь в этом, особенно с двигателем V8, каким он является. Я уверен, что есть несколько тестов производительности, но я бы не стал слишком об этом беспокоиться. Не тратьте время на микрооптимизацию, если в этом нет необходимости.
Джош Бим,

1
Большое спасибо! Это отличная информация, которую я получил от вас. И да, в микрооптимизации разбираться не буду.
bozzmob

Я нашел это объяснение полезным nikgrozev.com/2015/07/14/…
mwojtera

35

Async / Await обеспечивает гораздо более удобный синтаксис в более сложных сценариях. В частности, все, что связано с циклами или некоторыми другими конструкциями, такими как try/ catch.

Например:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

Этот пример был бы значительно более запутанным, просто используя промисы.


Это отличный пример, чтобы понять то же самое. Итак, когда дело доходит до производительности, нет никакой разницы между ними? А что лучше использовать в коде? Async Await кажется лучше, по крайней мере, после вашего примера.
bozzmob

1
@bozzmob: Нет разницы в производительности. Если вам удобно использовать async / await, я бы порекомендовал это. Сам я пока не использую, потому что на самом деле он не является частью официального стандарта.
Стивен Клири

Да, я согласен, что это не часть стандарта, но, в случае ReactJS (конкретно реагировать на нативный), я как бы вынужден использовать его в некоторых частях кода. Итак, половина из них - обещания, а половина - асинхронные ожидания. Итак, я задал вам эти вопросы. Спасибо за нужную информацию.
bozzmob

1
Я думаю, что многие люди сбиты с толку и / или введены в заблуждение, когда никто не использует блок try / catch в своих примерах кода.
Оги Гарднер

Вы имеете в виду это? const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux 03

14

Почему требуется async, await, когда Promises выполняет аналогичную работу? Решает ли async, await более серьезную проблему? или это было просто другое решение проблемы обратного вызова? Как я уже говорил ранее, я могу использовать Promises и Async, Await для решения той же проблемы. Есть ли что-нибудь конкретное, что решено с помощью Async Await?

Прежде всего вы должны понять, что async/ awaitsyntax - это просто синтаксический сахар, предназначенный для увеличения обещаний. Фактически возвращаемое значение asyncфункции - это обещание. Синтаксис async/ awaitдает нам возможность писать асинхронно в синхронном режиме. Вот пример:

Цепочка обещаний:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async функция:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

В приведенном выше примере awaitожидает fetch(url)разрешения или отклонения обещания ( ). Если обещание разрешено, значение сохраняется в responseпеременной, и если обещание отклоняется, оно выдаст ошибку и, таким образом, войдет в catchблок.

Мы уже видим, что использование async/ awaitможет быть более читабельным, чем цепочка обещаний. Это особенно верно, когда количество обещаний, которые мы используем, увеличивается. И цепочка обещаний, и async/ awaitрешают проблему ада обратного вызова, и какой метод вы выберете, зависит от личных предпочтений.


10

Полное сравнение с плюсами и минусами.

Обычный JavaScript

  • Плюсы
  • Не требует дополнительных библиотек или технологий
  • Предлагает лучшую производительность
  • Обеспечивает лучший уровень совместимости со сторонними библиотеками
  • Позволяет создавать специальные и более сложные алгоритмы
  • Минусы
  • Может потребоваться дополнительный код и относительно сложные алгоритмы

Async (библиотека)

  • Плюсы
  • Упрощает наиболее распространенные шаблоны управления потоком
  • Все еще является решением на основе обратного вызова
  • Хорошее исполнение
  • Минусы
  • Вводит внешнюю зависимость
  • Может все еще не хватить для продвинутых потоков

Обещания

  • Плюсы
  • Значительно упрощает наиболее распространенные схемы управления потоком.
  • Надежная обработка ошибок
  • Часть спецификации ES2015
  • Гарантирует отложенный вызов onFulfilled и onRejected
  • Минусы
  • Требуются API-интерфейсы promisify на основе обратного вызова
  • Небольшое снижение производительности

Генераторы

  • Плюсы
  • Делает неблокирующий API похожим на блокирующий
  • Упрощает обработку ошибок
  • Часть спецификации ES2015
  • Минусы
  • Требуется дополнительная библиотека потока управления
  • По-прежнему требуются обратные вызовы или обещания для реализации непоследовательных потоков
  • Требуется преобразование или обещание API без генераторов

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

  • Плюсы
  • Делает неблокирующий API похожим на блокирующий
  • Чистый и интуитивно понятный синтаксис
  • Минусы
  • Требуется Babel или другие транспилеры и некоторая конфигурация для использования сегодня

Откуда это было скопировано? По крайней мере, некоторые из них находятся на страницах 136-137 в книге Node.js Design Patterns (второе издание) (ISBN-10: 1785885588)
Питер Мортенсен

6

Async / await может помочь сделать ваш код более чистым и читаемым в тех случаях, когда вам нужен сложный поток управления. Он также создает более удобный для отладки код. И позволяет обрабатывать как синхронные, так и асинхронные ошибки с помощью только try/catch.

Недавно я написал этот пост, демонстрирующий преимущества async / await над обещаниями в некоторых распространенных случаях использования с примерами кода: 6 причин, почему JavaScript Async / Await удаляет обещания (Учебник)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.