使用服务获取ngrx和@Effect

时间:2017-10-06 17:06:17

标签: angular ngrx ngrx-store ngrx-effects

目前我正在尝试将令人敬畏的ngrx lib集成到我的项目中。一切都按照预期的@ ngrx / effects lib工作。我想要做的是从服务中获取我的一些数据,这将在稍后发出http请求。我知道我错过了一些东西,但我找不到我的误会。也许有些人可以提供帮助。

所以我在我的应用程序中有一个延迟加载的模块,我想使用ngrx lib。

到目前为止我的代码:

  

app.module.ts

import [...]
import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { EffectsModule } from '@ngrx/effects';

@NgModule({
    imports: [
        HttpModule,
        BrowserModule,
        BrowserAnimationsModule,
        ToastModule.forRoot(),
        FormsModule,
        SharedModule,
        ReactiveFormsModule,
        appRouting,
        StoreModule.forRoot({}),
        StoreDevtoolsModule.instrument({
            maxAge: 25
        }),
        EffectsModule.forRoot([])
    ],
    declarations: [
        AppComponent,
        NavigationComponent,
        HomeComponent,
        LoginComponent,
        SidebarComponent,
        PageNotFoundComponent
    ],
    providers: [
        AuthenticationService,
        AlertService,
        AuthGuard,
        mockBackendProvider,
        MockBackend,
        BaseRequestOptions,

        AppConfig,
        {
            provide: APP_INITIALIZER,
            useFactory: (config: AppConfig) => () => config.load(),
            deps: [AppConfig],
            multi: true
        },
        {
            provide: ToastOptions, useClass: NotificationOptions
        }
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}
  

project.module

import [...]
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { projectReducer } from './store/project.reducer';
import { ProjectService } from './services/project.service';
import { ProjectEffects } from './store/project.effects';

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        ReactiveFormsModule,
        ProjectRoutingModule,
        SharedModule,
        EffectsModule.forFeature([ProjectEffects]),
        StoreModule.forFeature('projectModule', {
            projectReducer: projectReducer,
        }),

    ],
    exports: [],
    declarations: [
        HomeComponent,
        DashboardComponent
    ],
    providers: [
        ProjectService,
        mockBackendProvider,
        MockBackend,
        BaseRequestOptions
    ],
})
export class ProjectModule {
}

我创建了4个文件:

  

project.actions.ts

import { Action } from '@ngrx/store';
import { Project } from '../../../models/Project/Project';

export const SELECT_ALL_PROJECTS = '[projects] Select all';
export const ADD_PROJECT = '[projects] Add project';
export const DELETE_PROJECT = '[projects] Delete project';

export class GetAllProjectsAction implements Action {
    readonly type = SELECT_ALL_PROJECTS;

    constructor(public projects: Project[]) {
    }
}

export class AddProjectAction implements Action {
    readonly type = ADD_PROJECT;

    constructor(public project: Project) {
    }
}

export class DeleteProjectAction implements Action {
    readonly type = DELETE_PROJECT;

    constructor(public project: Project) {
    }
}

export type Actions = GetAllProjectsAction | AddProjectAction | DeleteProjectAction;

projects.effects.ts

import { Injectable } from '@angular/core';
import {
    Actions,
    Effect
} from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { Action } from '@ngrx/store';

import * as projectAction from './project.actions';
import { ProjectService } from '../services/project.service';
import { of } from 'rxjs/observable/of';

@Injectable()
export class ProjectEffects {

    @Effect() getAll$: Observable<Action> = this.actions$.ofType(projectAction.SELECT_ALL_PROJECTS)
        .mergeMap(() =>
            this._projectService.getAll()
                .map((data: any[]) => ({type: projectAction.SELECT_ALL_PROJECTS, projects: data}))
                .catch((error: any) => {
                    return of({type: 'getALL_Failed'})
                })
        );

    constructor(private _projectService: ProjectService, private actions$: Actions) {

    }
}
  

projects.reducer.ts

import * as projectAction from './project.actions';

import { ProjectState } from './project.state';

export const initialState: ProjectState = {
    projects: [
        {id: 1, title: 'Project Alpha'}, {id: 2, title: 'Project Beta'}]
};

export function projectReducer(state = initialState, action: projectAction.Actions): ProjectState {
    switch (action.type) {
        case projectAction.ADD_PROJECT:
            return Object.assign({}, state, {
                projects: state.projects.concat(Object.assign([], state, action.project))
            });
        case projectAction.SELECT_ALL_PROJECTS:
            return Object.assign({}, state, action.projects);
        case projectAction.DELETE_PROJECT:
            return Object.assign({}, state, {
                projects: state.projects.filter(p => p.id !== action.project.id)
            });
        default:
            return state;
    }
}
  

projects.state.ts

import { Project } from '../../../models/Project/Project';

export interface ProjectState {
    projects: Project[];
}

最后我的服务:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import {Project} from "../../../models/Project/Project";

@Injectable()
export class ProjectService {

    projects: Project[] = [{
        id: 1,
        title: 'Project Alpha'
    }];

    constructor() {
    }

    getAll(): Observable<Project[]> {
        return Observable.of(this.projects);
    }
}

所以我在屏幕上看到的是2个初始项目,而不是项目服务给出的项目。看起来我在服务中或在reducer中做错了,或者我完全错过了其他的东西。

//更新: 我设法让效果起作用。好吧,至少效果被调用,但现在我被困在一个无限循环。该应用程序不会响应并显示白屏

也许有人可以帮助我 我在调用组件中的代码是:

    import {DELETE_PROJECT, SELECT_ALL_PROJECTS} from '../../store/project.actions';

@Component({
    selector: 'project-dashboard',
    templateUrl: 'dashboard.component.html',
    styleUrls: ['dashboard.component.scss']
})

export class DashboardComponent implements OnInit {

    public async: any;

    projectState$: Observable<ProjectState>;

    constructor(private store: Store<any>) {
        // this.store.dispatch({type: SELECT_ALL_PROJECTS});
        this.projectState$ = this.store.select<ProjectState>(state => state.projectModule.projectReducer);
    }

    ngOnInit() {
        this.store.dispatch({type: SELECT_ALL_PROJECTS, projects: []});
    }

    delete(project: Project) {
        this.store.dispatch({type: DELETE_PROJECT, project: project})
    }
}

感谢每一位帮助

此致

1 个答案:

答案 0 :(得分:0)

你的无限循环是由于效果调度了它所观察到的相同动作。您需要调度SELECT_ALL_PROJECTS_COMPLETE或类似物,然后在您的reducer中处理。

我意识到这是一个老问题,但也许它可以帮助别人,如果你设法自己解决这个问题:)