Чем thunks отличаются от саг?
Преобразователь — это функция, в которой уже есть все необходимое для выполнения.
Saga , Если вы являетесь или были поклонником фэнтези или научной фантастики, вы уже знаете. Для других сага — это просто серия связанных историй.
Redux-thunk и Redux-saga являются промежуточными библиотеками для Redux. Промежуточное ПО Redux — это код, который перехватывает действия, поступающие в хранилище через метод dispatch()
.
Действие может быть буквально любым.
Но если вы следуете рекомендациям, действие представляет собой простой объект JavaScript с полем type
и необязательными полями payload
, meta
и error
. Например.
const loginRequest = {
type: 'LOGIN_REQUEST',
payload: {
name: 'admin',
password: '123',
},
};
Вот как выглядит подпись типа в TypeScript
type Action = {
type: string;
payload?: any;
meta?: any;
error?: boolean;
};
Redux-Thunk
В дополнение к диспетчеризации стандартных действий промежуточное ПО Redux-Thunk позволяет вам отправлять специальные функции, называемые thunks.
Преобразователи (в Redux) обычно имеют следующую структуру:
export const thunkName =
parameters =>
(dispatch, getState) => {
// Your application logic goes here
};
То есть преобразователь — это функция, которая (необязательно) принимает некоторые параметры и возвращает другую функцию. Внутренняя функция принимает функцию dispatch
и функцию getState
— обе они будут предоставлены промежуточным программным обеспечением Redux-Thunk.
Здесь у нас есть пример thunk, который пытается вызвать API входа с именем пользователя и паролем. Преобразователь сначала отправляет действие, указывающее, что запрос запускается. Затем он делает вызов. Наконец, он отправляет либо действие успеха, либо действие отказа в зависимости от того, был ли вызов API успешным.
import * as api from 'api';
import { loginRequest, loginSuccess, loginFailure } from './loginActions';
export const loginThunk =
(name: string, password: string) =>
(dispatch: Function) => {
dispatch(loginRequest());
try {
api.login(name, password);
}
catch (err) {
dispatch(loginFailure(err));
return;
}
dispatch(loginSuccess());
};
Когда вы отправляете свой преобразователь, например. dispatch(loginThunk('admin', 'secret'));
Redux-Thunk вызывает вашу внутреннюю функцию, которая, по сути, такова:
(dispatch: Function) => {
dispatch(loginRequest());
try {
api.login('admin', 'secret'); // values from closure
}
catch (err) {
dispatch(loginFailure(err));
return;
}
dispatch(loginSuccess());
};
Теперь, когда мы рассмотрели основы Redux-thunk, давайте посмотрим на Redux-Saga.
Редукс-Сага
Промежуточное ПО Redux-Saga позволяет вам выражать сложную логику приложения в виде чистых функций, называемых сагами. Чистые функции желательны с точки зрения тестирования, потому что они предсказуемы и воспроизводимы, что делает их относительно простыми для тестирования.
Саги реализуются через специальные функции, называемые функциями-генераторами. Это новая функция JavaScript ES6. По сути, выполнение прыгает в генератор и выходит из него везде, где вы видите оператор yield
. Думайте об операторе yield
как о том, что генератор приостанавливает работу и возвращает полученное значение. Позже вызывающая сторона может возобновить работу генератора с оператора, следующего за yield
.
Генераторная функция определена следующим образом. Обратите внимание на звездочку после ключевого слова function.
function* mySaga() { // ...}
Мы можем переписать функциональность входа в систему как сагу. Это выглядит так:
import * as api from 'api'; import { LoginRequestAction, loginSuccess, loginFailure } from './loginActions';
function* loginSaga() { const action: LoginRequestAction = yield take('LOGIN_REQUEST'); const { name, password } = action.payload; try { yield call(api.login, name, password); } catch (err) { yield put(loginFailure(err)); return; } yield put(loginSuccess()); }
Как только сага входа будет зарегистрирована в Redux-Saga, она сразу же начнет выполняться. Но тогда yield take
в первой строке приостановит сагу до тех пор, пока действие с типом 'LOGIN_REQUEST'
не будет отправлено в хранилище. Как только это произойдет, выполнение продолжится.