Я использую пользовательское промежуточное ПО ( мета-редуктор ), чтобы печатать мои ngrx-store
каждый раз, когда действие отправляется.Я написал свое промежуточное программное обеспечение прямо внутри app.module.ts
(куда еще его поместить?):
app.module.ts
// ...imports
// ...
// FIXME:
/**
* console.log action and state(before action) each time an action is dipatched
* @param reducer reducer
*/
export function debug(reducer: ActionReducer<AppState, Actions>): ActionReducer<AppState, Actions> {
const logger = new LoggerService(); ////////////// ERROR \\\\\\\\\\\\\\
return (state, action) => {
logger.storeInfo('ACTION', action);
logger.storeInfo('STATE', state);
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<any>[] = [
debug,
];
@NgModule({
declarations: [AppComponent, LoggerServiceComponent],
entryComponents: [],
imports: [
// ...
StoreModule.forRoot(reducers, { metaReducers }),
StoreRouterConnectingModule.forRoot(), // Connects RouterModule with StoreModule
],
providers: [
// ...
],
bootstrap: [AppComponent],
})
export class AppModule {}
Произошла ошибка, потому чтоВ моем LoggerService
введено хранилище (потому что я хочу, чтобы все мои журналы были сохранены в ngx-store
. Но я не могу получить доступ и к хранилищу! . Более того, я уверен, что это нехорошоспособ доступа к одноэлементному экземпляру службы ...
- Должен ли я поместить свой метаредуктор в класс, а затем получить доступ к функции этого класса, но как мне это сделать?
- Существует ли общий способ доступа к какой-либо услуге, например
SomeClass.getServiceInstance(type)
? - У вас есть другие идеи о том, как это сделать?
[ПРАВИТЬ 1] - с помощьюMETA_REDUCERS
(1-я попытка - сбой)
app.module.ts
import { LoggerService } from './services/logger.service';
import { AppState, Actions } from './app.state';
import { StoreModule, MetaReducer, ActionReducer, META_REDUCERS } from '@ngrx/store';
/**
* Injects a `LoggerService` inside a `MetaReducer`
* @param logger a service that allows to log and store console.log() messages
* @returns a `MetaReducer`
*/
function debugFactory(logger: LoggerService): MetaReducer<AppState> {
return (reducer: ActionReducer<AppState, Actions>): ActionReducer<AppState, Actions> => {
return (state, action) => {
logger.storeInfo('ACTION', action);
logger.storeInfo('STATE', state);
return reducer(state, action);
};
};
}
/**
* Injects a LoggerService inside the debug `MetaReducer` function
* @param logger a service that allows to log and store console.log() messages
* @returns A list of `MetaReducer`
*/
export function getMetaReducers(logger: LoggerService): MetaReducer<AppState>[] {
return [debugFactory(logger)];
}
const reducers = {
layout: layoutReducer,
preferences: preferencesReducer,
router: routerReducer,
debug: debugReducer,
};
@NgModule({
declarations: [AppComponent ],
entryComponents: [],
imports: [
// ...
StoreModule.forRoot(reducers),
StoreRouterConnectingModule.forRoot(), // Connects RouterModule with StoreModule
],
providers: [
// ...
{
provide: META_REDUCERS,
deps: [LoggerService],
useFactory: getMetaReducers,
multi: true,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
Это должно работать, согласно документу, но у меня есть следующая ошибка ввремя выполнения:
TypeError: "fn is not a function"
Соответствует этой функции (в библиотеке njrx-store):
/**
* @param {...?} functions
* @return {?}
*/
function compose(...functions) {
return (/**
* @param {?} arg
* @return {?}
*/
function (arg) {
if (functions.length === 0) {
return arg;
}
/** @type {?} */
const last = functions[functions.length - 1];
/** @type {?} */
const rest = functions.slice(0, -1);
return rest.reduceRight((/**
* @param {?} composed
* @param {?} fn
* @return {?}
*/
(composed, fn) => {
return fn(composed) // <----- HERE
}), last(arg));
});
}
В отладчике показано, что функцияon массив (...functions
) содержит несколько функций и один массив, который, как я подозреваю, является результатом метода getMetaReducers
.Я подозреваю, что либо пример неправильный, либо есть проблема с реализацией метода compose
.
Скажите, если вы видите какие-либо неправильные вещи в моем коде.
[EDIT 2]- используя USER_PROVIDED_META_REDUCERS
, как указано в ответе (2-я попытка - не удалось)
код, который был отредактирован
// OLD
providers: [
// ...
{
provide: META_REDUCERS,
deps: [LoggerService],
useFactory: getMetaReducers,
multi: true,
},
],
// NEW
providers: [
// ...
{
provide: USER_PROVIDED_META_REDUCERS,
deps: [LoggerService],
useFactory: getMetaReducers,
},
],
Кажется, что мой LoggerService
либонеправильно передан или инициализирован, потому что у меня теперь есть эта ошибка:
core.js:9110 ERROR TypeError: Cannot read property 'storeInfo' of undefined
at http://localhost:8102/main.js:636:20
at http://localhost:8102/vendor.js:109798:20
at computeNextEntry (http://localhost:8102/vendor.js:108628:21)
at recomputeStates (http://localhost:8102/vendor.js:108681:15)
at http://localhost:8102/vendor.js:109029:26
at ScanSubscriber.StoreDevtools.liftedAction$.pipe.Object.state [as accumulator] (http://localhost:8102/vendor.js:109081:38)
at ScanSubscriber._tryNext (http://localhost:8102/vendor.js:120261:27)
at ScanSubscriber._next (http://localhost:8102/vendor.js:120254:25)
at ScanSubscriber.next (http://localhost:8102/vendor.js:114391:18)
at WithLatestFromSubscriber._next (http://localhost:8102/vendor.js:122330:34)
, если я прокомментирую эти строки:
logger.storeInfo('ACTION', action);
logger.storeInfo('STATE', state);
Не будет выдано никаких исключений, но мой регистратор тоже не будет работать.
Но, по крайней мере, хранилище настроено правильно, проблема в том, что служба LoggerService либо неправильно передана, ни инициализирована.Я думаю, я все еще делаю что-то не так