Страницы

Поиск по вопросам

среда, 19 декабря 2018 г.

Правильное использование async/await

Из прочитанного про async/await, я понял что эта конструкция должна упростить код, избавить разработчиков от лишних коллбэков. Я запустил такой пример:
var request = require('request'); var async = require('asyncawait/async'); var await = require('asyncawait/await');
function getQuote() { var quote;
return new Promise(function(resolve, reject) { request('http://ron-swanson-quotes.herokuapp.com/v2/quotes', function(error, response, body) { quote = body; resolve(quote); }); }); }
var main = async (()=>{ var quote = await(getQuote()); console.log(quote); });
main();
console.log('Ron once said,');
В консоли вижу следующее:
Ron once said, ["Great job, everyone..."]
Это говорит о том, что main() срабатывает после console.log('Ron once said,')
Но в чем суть тогда, если один-черт нужно передавать коллбэк в main() чтобы сначала получить результат запроса, а потом что-то с ним делать?
Как добиться того, чтобы в данном примере сначала сработал main() а потом console.log()?


Ответ

async определяет, что функция является асинхронной и позволяет использовать внутри нее оператор await, который приостанавливает выполнение функции, на время получения результата. Обращаю ваше внимание, что конструкцию await можно использовать не везде, а только внутри асинхронных функций.
До определения async/await подобно поведение достигалось использованием генераторов в комплекте с библиотеками, вроде co. Я уже детально расписывал этот подход в одном из своих ответов

Теперь несколько слов о вашем конкретном примере. Основная цель, насколько я могу видеть, в псевдо-синхронном выполнении связки:
main(); console.log('Ron once said,');
Казалось бы, функция main определена как асинхронная и этот блок должен выполняться последовательно. Однако вы упускаете один очень важный момент: определение функции асинхронной не делает ее вызов псевдо-синхронным автоматически. Вам нужно в явном виде дождаться результата выполнения main
Для этого нужно просто обернуть весь ваш код в IIFE-выражение, использующее асинхронную функцию и дождаться результата выполнения main
let getData = () => { return new Promise(function(resolve, reject) { setTimeout(() => { resolve('Great job, everyone...'); }, 500); }); };
(async () => { let main = async ()=> { console.log(await getData()); };
await main(); console.log('Ron once said,'); })();
Этот пример выведет:
Great job, everyone... Ron once said,
А вот и работающий пример на JSFiddle.
Замечание:
Код выше я написал на чистом JS, без использования библиотеки-полифила asyncawait. Если вы хотите использовать эту библиотеку, то вместо ключевых слов async/await вам нужно в явном виде вызывать функции этой библиотеки.
В качестве альтернативы, я бы предложил использовать Babel, превращающий ES 6/7 код в то, что уже сегодня можно запустить в большинстве браузеров.

Комментариев нет:

Отправить комментарий