【问题标题】:How to use async and await in NGRX effect of angular如何在 Angular 的 NGRX 效果中使用 async 和 await
【发布时间】:2021-03-05 14:58:12
【问题描述】:

我正在 Angular 11 中使用 NGRX(状态管理)。

我正在显示组件加载的租户列表。使用 NGRX 效果,实际上我通过服务请求 http 调用。

这是我的效果

@Injectable()
export class TenantsListEffects {
constructor(private actions$: Actions, private tenantListService: 
TenantAdministrationService) { }


loadTenants$ = createEffect(() => this.actions$.pipe(
ofType(TenantsListActions.TenantsListActionTypes.LoadTenantsLists),

switchMap(
  
  ((action) => this.tenantListService.getAllTenantsUsingGET().pipe(

  map(tenants => { return new TenantsListActions.LoadTenantsListsSuccess({ 
  data: tenants }) }),
    catchError(err => of(new TenantsListActions.LoadTenantsListsFailure({ 
  error: err })))
    )
    )
   ))
   )
  }

这是我的tenantList.reducer.ts

    export const tenantsListFeatureKey = 'tenantsListState';


    export interface tenantsListState {
     tenants: DisplayNameToTenantMappingResponse[],
     loading: boolean,
     error: string
    }

     export const initialState: tenantsListState = {
  tenants: [],
  loading: false,
  error: ''
};


export function reducer(state = initialState, action: TenantsListActions): tenantsListState {
  switch (action.type) {
    case TenantsListActionTypes.LoadTenantsLists:
      return {
        ...state,
        loading: true
      }
    case TenantsListActionTypes.LoadTenantsListsSuccess:
      return {
        ...state,
        tenants: action.payload.data,
        loading:false,
        error: null
      }
    case TenantsListActionTypes.LoadTenantsListsFailure:
      return {
        ...state,
        error: action.payload.error,
        loading: false
      }

    default:
      return state;
  }
}

这是我的选择器

const getTenantsListState = createFeatureSelector<tenantsListState>('tenantsListState');

export const getTenants = createSelector(
    getTenantsListState,
    state => state.tenants
)

export const getError = createSelector(
    getTenantsListState,
    state => state.error
)

这是我的服务

@Injectable({
providedIn: 'root'
})
export class TenantAdministrationService {
public basePath: string ='';
constructor(private basePathService: BasePathService,private http: 
HttpClient) {
this.basePath = this.basePathService.selectEnv();
}

public 
getAllTenantsUsingGET():Observable<DisplayNameToTenantMappingResponse[]>{
let test =  this.http.get<Array<DisplayNameToTenantMappingResponse>> 
(`${this.basePath}/admin/tenant`);
console.log('get list ', test);

return test
}

问题是

当我第一次调用该服务时,它没有重新调整任何内容,因此它没有在我的 ngrx 商店中存储任何东西。 但在 2 到 3 秒后,它会返回租户列表并作为状态存储在商店中。

我尝试为我的服务调用方法创建异步功能,但它导致效果错误。

那么有人可以帮我解决这个问题吗....

【问题讨论】:

  • 请添加真实代码,代码截图为无代码。
  • 嗨,我用真实代码编辑过。

标签: angular typescript ngrx


【解决方案1】:

看起来您的设置正确,但我在 switchMap 之后看到了一个额外的括号 (。像这样它应该可以工作。

loadTenants$ = createEffect(() => this.actions$.pipe(
  ofType(TenantsListActions.TenantsListActionTypes.LoadTenantsLists),
  switchMap(action => this.tenantListService.getAllTenantsUsingGET().pipe(
    map(tenants => new TenantsListActions.LoadTenantsListsSuccess({ data: tenants }),
    catchError(err => of(new TenantsListActions.LoadTenantsListsFailure({ 
  error: err })))
  )
);

请记住,您的 reducer 需要先将实体添加到状态,然后您的商店选择器才会发出它们。

const reducer = createReducer(
  initialState,
  on(TenantsListActions.LoadTenantsListsSuccess, (state, { data }) => featureAdapter.setAll(data, {
    ...state,
    isLoading: false,
    error: null,
  })),
  ...
);

上面我使用entity adapter 将实体添加到状态。

【讨论】:

  • 我发布了我的租户列表缩减程序,我如何修改我的代码以添加实体适配器。我已经阅读了文档,但我不明白
  • 您正在做的事情也应该有效。您是否删除了多余的括号?
  • 是的,我删除了多余的括号,但问题仍然存在
【解决方案2】:

我解决了我使用 state 属性加载并将其用作组件中的 observable 的问题。 `

export interface tenantsListState {
     tenants: DisplayNameToTenantMappingResponse[],
     loading: boolean,
     error: string
    }

`

在 http 调用期间,它变为 loading = true; 并触发了一个微调器,该微调器停止组件加载,直到返回 http 调用。

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2020-09-16
    • 2022-01-05
    • 2019-07-20
    • 2021-10-10
    相关资源
    最近更新 更多