Comments 22
Это и правда неюзабельно. Но еще подождите людей со стокгольмским синдромом)
Вопрос к тем, кто использует саги вместо thunk: а что именно в saga-ах вам понравилось больше, чем практически точно такой же async-await код + redux-thunk? Из статьи не совсем ясно. Пассаж про декларативность вызывает лишь улыбку (не ерунда же). У этого подхода (который, как мне показалось, в основном заключается в написании yield
вместо await
) есть какие-то более конкретные преимущества?
Ну просто это скорее декорация декларативности, нежели какая-то настоящая декоративность. Чем-то напоминает карго-культ. Каждая стадия конечного автомата генератора императивна. Да и генератор всё равно будет раскручен полностью. Async функции работают точно по тому же принципу, но запускаются JS-движком напрямую, а не через redux-saga. Какой-то существенной разницы я не вижу. Но звёздочки короче, тут спору нет :)
Это все же не так. Саги действительно декларативны — в том смысле, что итерация по генератору не вызывает выполнение сайд эффектов. Вместо этого генератор возвращает описание сайд эффектов в виде объекта-обертки (из примера в статье — вместо прямого вызова fetch()
и возврата результата промиса вызывается эффект call()
, который, вопреки названию, НЕ вызывает обернутую функцию :) ). Это позволяет более просто тестировать сагу (например, как здесь)
устраивает.
Лично я пользовался и тем, и другим. Разница между ними довольна большая.
redux-thunk удобный, простой как 5 копеек. Сайд эффекты описываются непосредственно в самих экшенах и вызываются как обычные.
redux-saga чуть более сложный и гибкий инструмент. Использует систему подписок — т.е. сага может быть вызвана на любой угодный вам экшен. Под гибкостью я имею ввиду более развитую систему эффектов — можно устраивать гонки эффектов, можно отменять действия и т.п.
Сравним на примере простой игры: надо нажать на кнопку и за 5 секунд сделать какое-то определенное действие, иначе проигрыш. В саге такое будет сделано за несколько строчек — гонка таймера и ожидание нового экшена. В redux-thunk сделать схожее уже на порядок сложнее.
Нельзя не отметить тестирование саг — очень простое и приятное занятие :)
Если у вас нет каких-то сложных действий используйте thunk, но если вы хотите больший контроль над потоком данных, удобное тестирование то saga ваш выбор.
Спасибо за разъяснение.
надо нажать на кнопку и за 5 секунд сделать какое-то определенное действие, иначе проигрыш. В саге такое будет сделано за несколько строчек — гонка таймера и ожидание нового экшена
Впечатляет. А можно, если не сложно, пример такой саги. Это одна сага или это две саги которые друг о друге что-то знают?
export function* startGame() {
const { winCondition, timeout } = yield race({
winCondition: take('WIN'),
timeout: call(delay, 5000)
})
if (winCondition) {
console.log("Yeee, you've just won!")
} else {
console.log("Oh, nooo! Time out")
}
}
Какая связь между отказом от саг и переходом на GraphQL?
Объясните мне пожалуйста, почему автор утверждает, что конструкции:
fetch(url).then(val => {
console.log(val)
})
и
var val = yield fetch(url);
console.log(val);
идентичны?
Ведь в первом варианте перменная val будет содержать результат запроса, который был передан в resolve функцию. А во втором случае val будет содержать Promise, состояние которого нам ещё нужно обработать.
Может быть автор хотел сказать, что «с помощью саги» (а не генератора) это будут идентичные выражения. Но, насколько я понимаю, это тоже неверно: чтобы эти варианты были едентичны, необходимо во втором случае fetch обернуть в saga/effects метод, например call, чтобы middleware распаковал значение промиса и вернул его в value.
Что-то вроде этого:
var val = yield call(fetch, url);
console.log(val);
Так, как это описано в статье — работать не должно. Или я чего-то не догоняю?
Да, имелся в виду генератор, который запускается middleware'ой.
Но, насколько я понимаю, это тоже неверно
yield'ить можно и промисы, middleware его подождет и без оборачивания в call
. Но таким образом теряется декларативность и по возможности лучше так не делать :)
Если есть несколько запросов, takeEvery стартует несколько экземпляров саги-рабочего
Скорее «рабочей саги»
Разбираемся в redux-saga: От генераторов действий к сагам