У меня есть идея отделить sagas
в соответствии с их ответственностью. Я создал базовый класс для обработчиков саги следующим образом.
export class BaseSagaHandler {
static isGenerator(fn) {
return fn.endsWith('Gen');
}
forkAllSagaFunctions() {
const sagaFuncs = [];
const functions = Object.getOwnPropertyNames(this.constructor.prototype);
functions.forEach(func => {
if (BaseSagaHandler.isGenerator(String(func))) {
sagaFuncs.push(fork([this, this[func]]));
}
});
return sagaFuncs;
}
}
Как видно из приведенного выше кода, я придерживаюсь соглашения, что нам нужно использовать все методы, которые заканчиваются на Gen
как Sagas
.
Вот пример дочернего класса
export class LocaleSaga extends BaseSagaHandler {
private localeService: ILocaleService;
constructor(localeService: ILocaleService) {
super();
this.localeService = localeService;
}
public* setCurrentLocale(locale) {
yield call([this, this.localeService.setCurrentLocale], locale);
yield put(WITH_PAYLOAD(SUCCESS(ACTION_TYPES.SET_LOCALE), locale));
}
public* setLocaleSagaGen() {
yield takeLatest(REQUEST(ACTION_TYPES.SET_LOCALE), this.setCurrentLocale);
}
}
Этот класс создается следующим образом.
const diContainer = rootDiContainer;
const localeSagas = new LocaleSaga(diContainer.get<ILocaleService>(LOCALE_SERVICE_TYPE)).forkAllSagaFunctions();
export default function* rootSaga() {
yield all([
localeSagas
]);
}
Так что в основном мы слушаем конкретное действие, а затем вызываем функцию. Однако у меня есть проблема в этой строке.
yield takeLatest(REQUEST(ACTION_TYPES.SET_LOCALE), this.setCurrentLocale);
Насколько я передаю метод класса, когда он достигает setCurrentLocale
, функция this
равна null
. Методы take*
не поддерживают передачу контекста, как я мог видеть из исходного кода и документации, но функции fork,call
позволяют передавать context
вместе с функцией.
Есть ли способ передать ссылку на метод класса в контексте класса?
P.S. Пожалуйста, дайте мне знать, есть ли в моей идее подводные камни или нет смысла.
Спасибо.
UPDATE
Благодаря ответу Андрея Моисеева я решил объединить два метода в один с функцией анонимного генератора следующим образом.
public* setLocaleSagaGen() {
const context = this;
yield takeEvery(REQUEST(ACTION_TYPES.SET_LOCALE), function* (locale) {
const result = yield call([context.localeService, context.localeService.setCurrentLocale], locale);
yield put(WITH_PAYLOAD(SUCCESS(ACTION_TYPES.SET_LOCALE), result));
});
}