Angular 6 обобщенная / абстрактная наблюдаемая функция - PullRequest
0 голосов
/ 05 марта 2020

Работа над приложением angular 6. Где я должен получить и отобразить список пользователей на каждой странице из API. Я написал функцию, которая прекрасно работает:

  listUsers() {
    let result = this.http.get('xyz.com/api/users');
    result.toPromise()
      .then(res => {
        this.userList = res.json();
       })
      .catch(err => {
        this.msgService.add({severity: 'error', summary: 'Internal Server Error',
        detail: 'There is an Server Error occurred. Please try again later.'});
    } );
  }

Моя проблема в том, что я хочу получать пользователей на более чем 10 компонентах / страницах. Я не хочу повторять (biolerplate) вышеупомянутую функцию listUsers() во всех этих 10 компонентах. Я хочу получить всех пользователей в единой центральной службе и получить к ней доступ из каждого компонента.

Как мне это сделать?

Извините, что я не правильно сформулировал вопрос. Также я не мог найти подобные посты по этому вопросу. Пожалуйста, укажите мне на пост, если он уже отвечал ранее. Я удалю этот повторяющийся пост.

Ответы [ 3 ]

2 голосов
/ 05 марта 2020

Это относится к вашей архитектуре в целом.

Если это в значительной степени единственный случай, который вас раздражает, я бы рекомендовал использовать shareReplay, чтобы вы могли поделиться результатами наблюдаемого со всеми потребители.

Пример:

@Injectable()
export class SomeService {
  // ...

  public users$: Observable<User[]> = this.http.get('xyz.com/api/users').pipe(
    catchError(err => {
      this.msgService.add({
        severity: 'error',
        summary: 'Internal Server Error',
        detail: 'There is an Server Error occurred. Please try again later.',
      });

      throw err;
    }),
    shareReplay({
      bufferSize: 1,
      // usually `refCount` should be true so that when all the subscribers
      // are not listening anymore, it'll close the observable but here let
      // imagine that all your components are not listening to that and then
      // later on you come back to it, it will return the previously fetched
      // data without fetching it again. If **in that special case** you'd
      // prefer to make another request turn that to true
      refCount: false,
    })
  );

  // ...
}

Таким образом, если у вас нет метода, одна и та же ссылка будет передана и использована. Благодаря shareReplay вы не сделаете еще один запрос, если все не откажутся от подписки, а позже кто-то другой подпишется на него. Но пока есть 1 подписчик, не имеет значения, сколько присоединится после, результат будет поделён.

Вы также можете рассмотреть поиск в этой библиотеке: https://github.com/ngneat/cashew, которая упростит вашу жизнь и даст вам больше контроля.

Другой вариант - начать изучать ngrx, так как было бы целесообразно получить данные один раз в зависимости от того, где вы находитесь на маршрутах (получить один раз) затем поместите его в локальное «хранилище», и все компоненты получат доступ к этому хранилищу. Но это потребует от вас изучения приставок / ngrx и не будет простым. Если ваше приложение продолжает расти, я бы рекомендовал проверить его, поскольку оно действительно полезно, но это решение остается за вами, и вы можете go с тем, что вам наиболее удобно.

0 голосов
/ 05 марта 2020

Вы можете использовать управление уровнем состояния, используя ngxs / store. Создайте один класс User-state.ts, который нуждается в следующих методах

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

    @Selector()
      static userList(state: UserStateModel) {
        return state.UserList;
      }

        const initialState = {
         UserList = []
        };

        // **make data base call to fetch User list**
          @Action(UserActions.GetUserList)
          getUserList(
            { patchState, dispatch }: StateContext<UserStateModel>,
            { payload }: UserActions.GetUserList
          ) {
            // call the service to backend call.
            return this.UserListService
              .getPayments(payload)
              .pipe(
                tap((apiResp: IApiResponse) => dispatch(new UserActions.GetUserListSuccess(apiResp))),
                catchError(error => {

                  return dispatch(new UserActions.UserListFail(error));
                })
              );
          }

          // Using **patchState** you can refresh value of UserList in store 
          @Action(UserActions.GetUserListSuccess)
          GetUserListSuccess(
            { patchState }: StateContext<UserStateModel>,
            { payload }: UserActions.GetUserListSuccess

          ) {

            if (!isNullOrUndefined(payload)
              && !isNullOrUndefined(payload.result)
              && !isNullOrUndefined(payload.resultdata)) {

              return patchState({
                UserList: payload.resultdata.UserList
              });
            }

            return **patchState**({ UserList: initialState.UserList});
          }

// Создать еще один файл UserAction.ts , который включает в себя ниже двух классов

export class GetUserList {
  static readonly type = '[UserList] Get Payment Details';  
}
export class GetUserSuccess {
  static readonly type = '[Userlist] Get User List Success';
  constructor(public payload?: any) { }
}
0 голосов
/ 05 марта 2020

Ngrx Превышение обслуживания

Нажмите здесь (Angular 6 - зачем использовать @ ngrx / store, а не внедрение службы ) .

Надеюсь, вы получите эту замечательную функцию, которая может быть использована для этой проблемы.

...