Как стать автором
Обновить

Комментарии 23

Типичная ошибка использования await — в функции convertCurrency есть два запроса (getExchangeRates и getCountries) которые друг друга не блокируют, но второй зачем то ждёт выполнения первого
То есть функция, которая внутри себя работает с, например, двумя асинхронными, может просто вызываться без всяких async/await? А сами асинхронные функции и так отработают по очереди?
Вы уверены? как мне кажется, если не ждать одну или другую, может случится казус, что вторая функция, которую ждали, отработает при том что первая нет. А тут мы уже отдачу делаем…
можно переписать, и выдавать информацию по поступлению, но если цель отдать инфу вместе… посему может есть ошибка в дизайне, но не в использовании await
Promise.all()
Статья, заметьте, про async/await, объясняющая функционал наглядным примером.
Удержание равновесия на мотоцикле можно показать на велосипеде, если цель в постановке примера…
я статью не читал. обычно при описании await первым делом говорят, что это — те же обещания, только в более удобной форме. соответственно, для понимания работы await нужно знать как работают обещания и какие для них есть полезные функции, та же Promise.all().
достаточно прочитать наименование статьи… ;)
Я не спорю, и Вы и lleo_aha в корне правы.
Однако, это как мне кажеться, как писать в каждой статье «Как написать xyz на PHP», что питон лучше. В корне может и так оно и есть, но это не отменяет права на использование PHP для решения задачи. Так и await/async, как мне кажется более или менее был показан конструкт сей функции автором. Реализация примера для этих целей, второстепенна, если она исчерпывающая.
если было бы важно выполнять функции паралельно то по моему без Promise.all не обойтись.
можно написать
async function parallel(m){return await Promise.all(m)};
и потом обращаемся
const m=await parallel([getExchangeRate(fromCurrency, toCurrency),getCountries(toCurrency)]);
получим массив из двух ответов
можете объяснить, чем Ваш пример лучше авторского?
по факту идёт тоже самое, только написано по другому. Или я не прав?
У автора выполняются последовательно
getCountries запустится когда придет ответ от getExchangeRate
у меня они одновременно запускаются
понятно, я «плоско» думал только о результате, но Ваш пример по теории быстрее отработает. спасибо
async function parallel(m){return await Promise.all(m)};

А какой смысл в этой функции? Скрыть из кода упоминание Promise? Но асинхронная функция всегда возвращает обещание, поэтому было бы достаточно написать так:
function parallel(m){return Promise.all(m)};

Эффект тот же, но работать будет быстрее, так как не создает совершенно лишнее по смыслу обещание-обертку, которое разрешается после разрешения обещания Promise.all(). Проверял только на NodeJS v8.11.3, возможно, когда-нибудь оптимизатор и такие вещи научится упрощать.

Но на мой взгляд, гораздо лучше вызывать Promise.all() напрямую, без оберток. В любом сколько-нибудь реальном применении async/await все равно придется разбираться с обещаниями, так что скрывать их из кода нет смысла.
Да там внутри функции await лишнее.
Спасибо.
Смысл избавится в основном коде от промисов.
Пример без этой функции ниже тут два раза написали
Можно обойтись, но выглядит мусорно.
let p1 = prom1()
let p2 = prom2()
let r1 = await p1
let r2 = await p2
Здесь удержание равновесия демонстрируется на трёхколёсном велосипеде, что может дать неверное представление о паттернах асинхронного программирования, ну, или удержания равновесия. Небольшое усложнение в виде Promise.all немного расширит кругозор и покажет, как делать правильнее.
promise.all, как мне кажется, делает то тоже самое… Если нет, можете объяснить что происходит в авторском примере под компотом и что в Вашем. Спасибо
UPDATE: мне ответили уже Выше, спасибо. с промисами работа будет паралельной и поидеи отработает быстрее…
а как в данном случае правильно сделать так чтобы они друг друга не блокировали, но дальнейший код выполнялся только после завершения обоих запросов?

Использовать Promise.all


const convertCurrency = async (fromCurrency, toCurrency, amount) => {
    const [exchangeRate, countries] = await Promise.all([
        getExchangeRate(fromCurrency, toCurrency),
        getCountries(toCurrency),
    ]);
    const convertedAmount = (amount * exchangeRate).toFixed(2);

    return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;
};

async/await — это те же самые промисы, просто с альтернативным синтаксисом, поэтому вместо await для каждой отдельной функции можно использовать await Promise.all.


const convertCurrency = async (fromCurrency, toCurrency, amount) => {
    const [ exchangeRate, countries ] = await Promise.all([
        getExchangeRate(fromCurrency, toCurrency),
        getCountries(toCurrency)
    ]);
    const convertedAmount = (amount * exchangeRate).toFixed(2);

    return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;
};

Upd: Прошу прощения за похожий ответ. На момент публикации моего комментария, других ответов не было, но мой комментарий проходил премодерацию.

я не понимаю зачем для даной задачи использовать асинхрон? зачем все так сложно? можно сделать функцию что приймет валюту и по формуле даст результат при клике на кнопку Результат или создать собитие addEventListener, (что есть вроде тоже асинхроним собитием) и при вводе суми в input слушать его собите изменения значения… без всяких там ожиданий первой под фунции, для виполнения второй под функции

напишите реальний пример, боевой из прода, но простой для чайника, плз)
Так вот тебе реальный пример из прода в статье. Получение данных из апи. При чем здесь ивентЛисенер? Пока промис не отработает, тебе инфа не придёт. Надо дождаться. Можно ждать колбэками, можно промисами, можно асинками. Просто асинки удобны. Грубо говоря, пока не выполнится первый await, второй будет ждать. Второму надо получить инфу из первого. Без нее он будет работать с undefined. Если я правильно понял пример.

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

await нельзя использовать нигде кроме как внутри async функций, иначе получится
SyntaxError: await is only valid in async functions and async generators


А если необходимо дождаться выполнения промиса вне async функции, придётся использовать старые добрые .then/.catch.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий