Angular 13 具有 ngrx 效果从 Api 返回数据

Angular 13 with ngrx effects returning data from Api

我是 ngrx 的新手,我正在尝试 return 来自 api 调用的数据在我的效果中,但是我没有正确构建我的效果,我不知道如何更正它的效果。

所以首先,我有一个调用 Api:

的通用方法
export class CrudService {

//Rest Api
endpoint = 'http://localhost:4200';

constructor(private httpClient: HttpClient) { }

httpHeader = {
  headers: new HttpHeaders({
    'Content-Type': 'aplication/json'
  })
}

getAll<T>(apiMethod: string): Observable<T> {

let callPoint = this.endpoint.concat('/', apiMethod);

return this.httpClient.get<T>(callPoint)
  .pipe(
    retry(1),
    catchError(this.processError)
  )
}.....

我的动作文件是:

import { Action } from '@ngrx/store';
import { Swivlr } from '../../Models/swivlr.model';

 export const ADD_SWIVLR = '[SWIVLR] Add';
 export const REMOVE_SWIVLR = '[SWIVLR] Remove';
 export const GET_SWIVLR = '[SWIVLR] Get';
 export const FAIL_SWIVLR = '[SWIVLR] Fail';

 export class AddSwivlr implements Action {
   public readonly type = ADD_SWIVLR;

   constructor(public payload: Swivlr) { }
 }

 export class RemoveSwivlr implements Action {
   public readonly type = REMOVE_SWIVLR;

   constructor(public payload: number) { }
 }

 export class GetSwivlr implements Action {
   public readonly type = GET_SWIVLR;

   constructor(public payload: Swivlr[]) { }
 }

 export class FailSwivlr implements Action {
   public readonly type = FAIL_SWIVLR;
   constructor(public error: string | null) { }
 }

 export type Actions = AddSwivlr | RemoveSwivlr | GetSwivlr | FailSwivlr;

所以现在在我的效果文件中,我正在尝试编写获取所有记录的效果:

import { RemoveSwivlr, AddSwivlr, GetSwivlr, GET_SWIVLR, FAIL_SWIVLR, FailSwivlr } from '../Actions/swivlr.actions';
import { AppState } from '../../app/app.state';
import { CrudService } from '../crud/generic-crud';
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { catchError, map, Observable, of, switchMap } from 'rxjs';
import { Swivlr } from '../../Models/swivlr.model';

@Injectable()
export class SwivlrEffects {
  constructor(private crudService: CrudService,
    private readonly actions$: Actions
  ) { }

  public readonly getSwivlr$: Observable<any> = createEffect(() => {
    return this.actions$.pipe(ofType(GET_SWIVLR),
      switchMap(() => of(this.crudService.getAll<Swivlr[]>('endpointAddress'))),
      map((payload: Swivlr[]) => new GetSwivlr(payload)),
      catchError((error: string | null) =>
        of(new FailSwivlr(error)))
    );
  });
}

编译器不喜欢我的 switchMap 行,我希望这是因为我没有订阅我的 getAll 方法,我不确定在这种情况下我应该如何订阅。

我的模型已声明:

export interface Swivlr {
  key: string;
  name: string;
  url: string;
  width: string;
  height: string;
}

任何关于我应该如何正确构建我的效果的帮助将不胜感激。

感谢@Deitsch,我将效果更改为:

public readonly getSwivlr$: Observable<any> = createEffect(() => {
    return this.actions$.pipe(ofType(GET_SWIVLR),
      mergeMap(() => this.crudService.getAll<Swivlr[]>('endpointAddress').pipe(
      map((payload: Swivlr[]) => new GetSwivlr(payload)))),
      catchError((error: string | null) =>
        of(new FailSwivlr(error)))
    );
  });

您创建效果的语法错误。查看 ngrx.io/guide/effects 处的 movie.effects.ts 并将其用作起点。将 API 调用替换为您的调用,然后从那里开始。

getSwivlr$ = createEffect(() => {
    return this.actions$.pipe(ofType(GET_SWIVLR), // use reference, not just same string!!
      mergeMap(() => this.crudService.getAll<Swivlr[]>('endpointAddress').pipe(
      map((payload) => new GetSwivlr(payload)))),
      catchError((error) => of(new FailSwivlr(error)))
    );
});

此外,您无需在任何地方手动添加输入。 Typescript 会为您正确处理它——如果有问题,它会告诉您。目前它非常混乱,实际上没有添加任何东西。

您也不应将 this.actions$.pipe(ofType(GET_SWIVLR) 中的类型 GET_SWIVLR 作为字符串引用 - 它很容易在您不注意的情况下中断。参考正确的操作类型!

在给定的 link 上,当您使用 switchMap 时会使用 mergeMap - 两者都有各自的用例,请阅读更多相关信息 blog.angular-university.io/rxjs-higher-order-mapping

另一件事是您创建的动作。它按照您的方式工作,但我建议您使用文档 ngrx.io/guide/store/actions

中的 createAction 方法