#javascript #design-patterns #dependency-injection #redux #redux-saga
#javascript #шаблоны проектирования #внедрение зависимостей #redux #redux-saga
Вопрос:
Как мне использовать DI в redux-sagas. У меня есть следующая сага
export function* loadUsers() {
// Want to use something like userService.loadUsers()
}
Как показано в приведенном выше коде, как мне внедрить UserService в saga, в идеале я хотел бы что-то вроде этого
export function* loadUsers(userService) {
userService.loadUsers()
}
Спасибо
Ответ №1:
Как внедрить зависимости в redux-sagas?
Как мне использовать DI в redux-sagas?
Вы можете сделать это с помощью API Redux saga, у вас есть доступ к getContext
и setContext
методам, которые позволяют вам управлять контекстом внутри ваших саг. Давайте посмотрим, как это работает!
Внедрите свой контекст
При вызове createSagaMiddleware
вы можете передать контекст. Позже мы увидим, как получить ваш контекст в ваших sagas
Вот как внедрить контекст в redux-saga:
import { createUserService } from "...";
import createSagaMiddleware from "redux-saga";
const userService = createUserService(...);
const sagaMiddleware = createSagaMiddleware({
context: {
userService
}
});
sagaMiddleware.run(rootSaga);
Получите ваш контекст
Вы можете импортировать getContext
из redux-saga / effects, а затем вызвать getContext
с ключом нужного вам контекста. Таким образом, вы получите userService
в этом случае.
import { getContext } from "redux-saga/effects";
export function* loadUsersSagas(action) {
const userService = yield getContext("userService");
const users = yield userService.loadUsers();
...
}
Тестирование
Как мы можем протестировать контекст с помощью redux-saga Вы можете использовать redux-saga-test-plan. Цель этой библиотеки — протестировать наши саги.
Что мы хотим сделать?
- Добавляйте поддельный контекст в наши тесты
- Убедитесь, что мы пытаемся получить правильный элемент в контексте
С помощью provide
мы приводим [[getContext("userService"), { loadUsers }]]
это издевательский контекст для userService
.
С помощью getContext
мы проверяем, получаем ли мы правильный элемент в контексте здесь: userService
import { getContext } from "redux-saga-test-plan/matchers";
describe("Load users", () => {
it("should load mocked users", () => {
const loadUsers = () => Promise.resolve([johnDoe]);
const action = createAction(...);
return expectSaga(loadUsersSagas, action)
.provide([[getContext("userService"), { loadUsers }]])
.getContext("userService")
.call(...)
.put(...)
.run();
});
});
Я надеюсь, что мой ответ поможет вам 😊
Ответ №2:
export function* loadUsers(userService) {
userService.loadUsers()
}
в другом месте:
export default function* rootSaga(userService) {
yield all([
...,
...,
loadUsers(userService)
]);
}
и затем:
import { createUserService } from "...";
import createSagaMiddleware from "redux-saga";
const userService = createUserService(...);
const sagaMiddleware = createSagaMiddleware();
sagaMiddleware.run(
rootSaga,
userService
)
Комментарии:
1. Как вы получили действие сейчас?