Почему я получаю несколько результатов выбора? - PullRequest
1 голос
/ 24 апреля 2020

В настоящее время я отправляю событие для извлечения всех данных из бэкэнда, и с помощью этой отправки я популяризирую копию состояния.

Пока все хорошо, проблема в том, что на бэкэнде нет ничего, что я потребовалось бы отправить событие для создания данных на нем и в новой копии состояния.

Для этого я использовал селектор, чтобы проверить, есть ли уже что-то в состоянии, потому что если оно там есть будет в бэкэнде, его проблема в том, что результат прибывает несколько раз, и задержка такая же, как на изображении ниже:

enter image description here Вот мой код:

КОМПОНЕНТ ПРИЛОЖЕНИЯ

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
    title = 'webwhatsapp';
    protected peoples: Array<IPeople> = [
        { id: '0', isMain: true, name: 'THIAGO DE BONIS CARVALHO SAAD SAUD', avatar: 'assets/users/thiagobonis.jpg', messages: null },
        { id: '1', isMain: false, name: 'BILL GATES', avatar: 'assets/users/billgates.jpg', messages: null },
        { id: '2', isMain: false, name: 'STEVE JOBS', avatar: 'assets/users/stevejobs.jpg', messages: null },
        { id: '3', isMain: false, name: 'LINUS TORVALDS', avatar: 'assets/users/linustorvalds.jpg', messages: null },
        { id: '4', isMain: false, name: 'EDSGER DIJKSTRA', avatar: 'assets/users/dijkstra.jpg', messages: null },
    ];

    constructor(private readonly peopleDispatchService: PeopleDispatchService, private readonly peopleSelectorsService: PeopleSelectorsService) {}

    ngOnInit(): void {
        this.peopleDispatchService.getAll();
        this.peopleSelectorsService.total.subscribe((total) => {
            console.log(total);
            if (total === 0) {
                // this.peoples.forEach((people) => this.peopleDispatchService.create(people));
            } else {
            }
        });
    }
}

РЕДУКТОРЫ

export interface State extends EntityState<IPeople> {
    error: IRequestError | null;
    loading: boolean;
}

export const adapter: EntityAdapter<IPeople> = createEntityAdapter<IPeople>({
    selectId: (people) => people.id,
});

const INIT_STATE: State = adapter.getInitialState({
    error: null,
    loading: true,
});

const peopleReducer = createReducer(
    INIT_STATE,
    on(fromPeopleAction.GET_ALL_SUCCESS, (state, { peoples }) => adapter.addMany(peoples, { ...state, loading: false })),
    on(fromPeopleAction.GET_ALL_FAIL, (state, { error }) => ({ ...state, error, loading: false })),
    on(fromPeopleAction.CREATE_SUCCESS, (state, { people }) => adapter.addOne(people, { ...state, loading: false })),
    on(fromPeopleAction.CREATE_FAIL, (state, { error }) => ({ ...state, error, loading: false })),
    on(fromPeopleAction.DELETE_SUCCESS, (state, { id }) => adapter.removeOne(id, { ...state, loading: false })),
    on(fromPeopleAction.DELETE_FAIL, (state, { error }) => ({ ...state, error, loading: false }))
);

export function reducer(state: State | undefined, action: Action) {
    return peopleReducer(state, action);
}

ЭФФЕКТЫ

@Injectable()
export class Effects {
    constructor(private action$: Actions, private backend: BackendService, private requestHandler: RequestHandlerService) {}

    getAll$ = createEffect(() =>
        this.action$.pipe(
            ofType(fromPeopleActions.GET_ALL),
            mergeMap(() => {
                return this.backend.getAll().pipe(
                    map((peoples) => fromPeopleActions.GET_ALL_SUCCESS({ peoples })),
                    catchError((error) => of(fromPeopleActions.GET_ALL_FAIL({ error: this.requestHandler.getError(error) })))
                );
            })
        )
    );

    create$ = createEffect(() =>
        this.action$.pipe(
            ofType(fromPeopleActions.CREATE),
            mergeMap((action) => {
                return this.backend.create(action.people).pipe(
                    map((people) => fromPeopleActions.CREATE_SUCCESS({ people })),
                    catchError((error) => of(fromPeopleActions.CREATE_FAIL({ error: this.requestHandler.getError(error) })))
                );
            })
        )
    );

    deleteAll$ = createEffect(() =>
        this.action$.pipe(
            ofType(fromPeopleActions.DELETE),
            mergeMap((action) => {
                return this.backend.delete(action.id).pipe(
                    map(() => fromPeopleActions.DELETE_SUCCESS({ id: action.id })),
                    catchError((error) => of(fromPeopleActions.DELETE_FAIL({ error: this.requestHandler.getError(error) })))
                );
            })
        )
    );
}

селекторы

const featureSelector = createFeatureSelector<State>('people');

export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors(featureSelector);

export const getError = createSelector(featureSelector, (state: State) => state.error);
export const getIsMain = createSelector(featureSelector, (state: State) => {
    state.ids.forEach((id: any) => {
        if (state.entities[id].isMain) {
            return state.entities[id];
        }
    });
});

1 Ответ

0 голосов
/ 05 мая 2020

Я бы порекомендовал вам использовать тот же эффект для обнаружения пустого состояния бэкэнда.

В getAll$ вы можете проверить после ответа, если бэкэнд пуст, если он есть - отправить действие для его заполнения. , Например, PopulatePeople.

    getAll$ = createEffect(() =>
        this.action$.pipe(
            ofType(fromPeopleActions.GET_ALL),
            mergeMap(() => {
                return this.backend.getAll().pipe(
                    tap(people => people.length === 0 ? this.store.dispatch(fromPeopleActions.POPULATE()) : undefined)
                    // ....
                );
            })
        )
    );

Затем вам нужен еще один эффект для прослушивания PopulatePeople.

populate$ = createEffect(() =>
  this.action$.pipe(
    ofType(fromPeopleActions.POPULATE),
      tap(() => this.peoples.forEach((people) => this.peopleDispatchService.create(people))),
  )
);

, в этом случае POPULATE запускается только тогда, когда бэкэнд действительно пуст.

...