Pull to refresh

Comments 18

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

Что-то типа Promise.all()?

Когда вам нужно сделать цепочку асинхронных вызовов, в которой последующее действие зависит от результата предыдущего, да еще и с ветвлениями, Promise.all() не подойдет… с промисами тот еще кодхелл будет.
Может, конечно, такие задачи и не часто встречаются, но когда встречаются — генераторы очень быстро снимают головную боль)
UFO just landed and posted this here
а зачем лишние зависимости, если все реализуется при помощи родных (с поправкой на поддержку браузерами) инструментов?

Я бы не согласился по поводу применять, redux-saga позволяет легко писать тестируемый код на генераторах, и они оказываются проще, чем rxjs подход в ngrx.

Генераторы есть во многих языках, зачем от них отказываться?

Если речь идет о библиотеке co, то она была создана до того как async/await был добавлены в nodejs и реализовывала возможность писать код без callback hell-а.

После появления async/await необходимость в co отпала, самым популярным фреймворком, который популяризировал использование co был koajs v1.x. Новая версия koajs v2.x на использование генераторов выдает «warning» с «deprecated».

Суть этой истории сводится к тому что не нужно использовать генераторы не по назначению, а не к принципиальному отказу от использования генераторов.
На мой взгляд, генераторы, это самая странная фича ES6. Т.е. она логичная и полезная, yield иногда нужен, но иногда, это пару раз в год… Т.е. достаточно странный синтаксис (звёздочка в функции, всё время забываю куда её правильно ставить, ключевое слово yield или yield return?, соглашения на имена next и value) и ради того, чтобы возвращать итерируемые объекты.
При этом, на самом деле, все любители извращений тайно потирали руки и ждали реализации генераторов ради того, чтобы костылить на них эмуляцию async/await. И сразу после появления сделали пачку библиотек, которые это делают. Получается, возможность генераторов изначально все планировали использовать не по назначению.

Другими словами, добавили фичу, которую все используют для других целей. Может быть стоило сразу использовать async/await и забить на эти генераторы?
К сожалению, генераторы до сих пор мощнее чем async/await. Например, с помощью async/await нельзя сделать асинхронный action в mobx без боли (а с помощью генератора — можно). Опять же, redux-saga использует именно генераторы.

Но в целом согласен. Кстати, в C++ посмотрели на это, да в Coroutines TS генераторы и асинхронные функции ввели одновременно, причем именно yield оказалось реализовано через await, а не как обычно.
Например, с помощью async/await нельзя сделать асинхронный action в mobx без боли (а с помощью генератора — можно)

А можно пример? Просто интересно, что там такое хитрое.

Вот так это делается с async/await:


@action
async foo() {
    const result = await fetch(...);
    const data = await result.json();
    runInAction(() => {
        // без runInAction будет лишний рендер, потому что mobx не может отловить асинхронные продолжения и обернуть их в транзакцию
        this.bar = data.bar;
        this.baz = data.baz;
    });
}

А вот так это делается с генератором:


foo = flow(function * () {
    const result = yield fetch(...);
    const data = yield result.json();

    // поскольку mobx сама управляет вызовами продолжений нет никаких проблем обернуть каждое в транзакцию автоматически, runInAction не нужен
    this.bar = data.bar;
    this.baz = data.baz;
})

Я правильно понимаю суть? В варианте с await если убрать runInAction, то после this.bar = ; мы получим render, а потом ещё и после this.baz = ;, т.к. рендер синхронный? А в случае * mobx не обновляет при детекте изменений до тех пор, пока не получит через yield что-нибудь асинхронное, или генератор просто не кончится? Т.е. тут решает все проблемы ручная обработка каждого yield, позволяя сделать больше, чем написано в коде?

Суть вы уловили правильно, но придумали переусложненный алгоритм. Функция flow просто оборачивает все вызовы next в runInAction.

Услышав высказывание «yeld pauses function execution» оно же «останавливает исполнение функции» — нужно остановить говорящего и настойчиво попросить быть корректным в формулировках. После точного «каждый yeld задает очередное состояние итератора возвращенного функцией» у автора бы не получилось статьи, но мы бы сэкономили время.
Я использовал генераторы в тестировании мобильных. У меня был объект, содержащий объекты с описанием устройств. Нужно было иметь возможность одновременно обращаться к конкретному девайсу по ключу и проходить по всем девайсам в цикле. Для этого я использовал генераторы. Функция возвращает объект, по которому можно бегать форычём и брать конкретный девайс по ключу. Плюс, если я хочу что-то подебажить, то мне не нужны все девайсы. Для этого был флаг в .env и по этому флагу генератор итерировался только по одному девайсу. Получилось очень удобно и достаточно просто. Не сказал бы что можно позволить себе не знать конструкции языка, доступные из коробки.
реализация хелпера

Чёж пример async/await не показали, ради которого всё писалось, а какой-то устаревший co есть, как-будто старая статья...

В корне не согласен с автором
До сих пор мы, работая с JS-функциями, ожидали, что они, будучи вызванными, просто выполняются от начала до конца

Ну и что? А теперь появился новый вид функции. Если чего-то раньше не было, значит никогда это не использовать?

Ссылки на async/await на мой взгляд притянуты за уши. Да когда не было async/await можно было писать aync/await-образный код при помощи генераторов, но вообще они не об этом.
Генератор это вещь которая может вернуть коллекцию чего-то без предварительного выделения памяти под коллекцию, в том числе коллекция может быть бесконечной.

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

Другой пример при помощи генератора можно создавать интерфейс для итерации по нескольким существующим коллекциям.
Sign up to leave a comment.