Чем 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' не будет отправлено в хранилище. Как только это произойдет, выполнение продолжится.