Как я могу заполнить статический массив внутри службы из запроса GET? - PullRequest
1 голос
/ 04 июня 2019

То, что я пытаюсь сделать (я так думаю), очень просто. Я создаю веб-приложение, и есть некоторые элементы select, которые я хочу заполнить одними и теми же данными из удаленного файла JSON (запрос GET). Я создал сервис , и я хочу заполнить статический массив внутри и вызывать его из любого компонента, который я хочу. Я думаю, что я скучаю по чему-то очень важному.
Вот некоторый код:
fetchData.service.ts

export interface Creditor {
  id: number;
  name: string;
}

@Injectable()
export class FetchDataService {

    creditorsStaticArray: Creditor[] = [];

    getCreditorsFromAPI() {
        this.http.get<Creditor[]>(this.creditorsUrl)
            .subscribe(
              items => {
                this.creditorsStaticArray = items;
              }
            );
      }

    getCreds() {
        return this.creditorsStaticArray;
    }
}

application-details.component.ts (один из компонентов)

export class ApplicationDetailsComponent implements OnInit {

    loadedCreditors: Creditor[] = [];

    constructor(private fetchDataService: FetchDataService) { }

    ngOnInit() {
        this.fetchDataService.getCreditorsFromAPI();
        this.loadedCreditors = this.fetchDataService.getCreds();
    }

}

Мое решение основано на этом ответе

Любая помощь будет высоко ценится!

Ответы [ 2 ]

4 голосов
/ 04 июня 2019

Ваш статический массив не может быть вне области вашего сервиса. Тем не менее, вы не можете иметь static внутри вашего class scope.

Поскольку services в Angular по умолчанию равны singletons, ваша целевая цель будет достигнута, выполнив что-то вроде этого:

@Injectable()
export class FetchDataService {

    creditorsStaticArray: Creditor[] = [];

    getCreditorsFromAPI() {
        this.http.get<Creditor[]>(this.creditorsUrl)
            .subscribe(
              items => {
                this.creditorsStaticArray = items;
              }
            );
      }

    getCreds() {
        return this.creditorsStaticArray;
    }
}

Поскольку вы уже ссылаетесь на this.creditorsStaticArray, это мгновенно сработает. Возможно, вы захотите переименовать его в creditorsCache или что-то в этом роде и запретить прямой доступ к нему извне службы (сделав его private), поскольку он больше не static. Но помимо соглашений об именовании и ограничителей доступа, вы достигаете цели того, что ищете.


Теперь я добавлю здесь несколько лучших практик для вашего дальнейшего использования.

Вы подписываетесь внутри своего Сервиса, а не управляете подпиской "явно". Это не обязательно плохо, так как по умолчанию HttpClient завершится после первого результата, но, возможно, стоит сделать это более явным, добавив .pipe(first()) или .pipe(take(1)) (first - псевдоним take(1)) , Таким образом, если ваш API или способ извлечения данных изменяется, есть явное напоминание, что этот Observable примет 1 значение (весь массив) и завершит себя, сохранив результат в переменную в качестве побочного эффекта.

То, что вы можете рассмотреть, - это не subscribing внутри вашего Сервиса, а возвращение всего Observable вашим компонентам, чтобы оно прошло и решило момент подписки. Вы все еще можете сохранить состояние вашей переменной, поместив его в

.pipe(
   tap(data => { this.creditorsCache = data })
)

Когда вы или ваш компонент (или ваш HTML с помощью AsyncPipe) подписываетесь; он сохранит его в своем кэше, и вы сможете автоматически обрабатывать новые входящие результаты.

В приведенном выше примере вы все еще можете положиться на свой механизм caching, чтобы не каждый раз попадать на ваш сервер, возвращая ваши кэшированные данные как Observable. К счастью, RxJS предоставляет множество возможностей Observables, чтобы это не было слишком сложным!

Быстрый пример:


getCreditorsFromAPI(): Observable<Creditor[]> {
  return this.http.get<Creditor[]>(this.creditorsUrl)
            .pipe(
                tap(data => this.creditorsCache = data)
             )
  );
}

getCreds(): Observable<Creditor[]> {
    // You could also use this to invalidate your cache after 10 minutes!
    if(this.creditorsCache.length > 0) {
        return of(this.creditorsCache)
    }

    // Because I set the return type of this function, you will need to return a valid Observable. This makes your code predictable!
    return this.getCreditorsFromAPI() // This will recreate your cache cause of the tap()!
}

В приведенном выше примере вам нужно только позвонить service.getCreds() и управлять подпиской в ​​своем компоненте. Он будет автоматически кешироваться каждый раз, когда вы переназначаете свой наблюдаемый на this.service.getCreds().

Пища для размышлений! Я бы не сказал, что есть идеальный способ сделать что-то, и есть определенно больше путей, которые ведут к образному Риму; но то, что я только что описал, определенно немного больше Reactive, на что полагается Angular для большинства своих внутренних компонентов.

1 голос
/ 04 июня 2019

Возврат Наблюдаемый от вашего сервиса:

@Injectable()
export class FetchDataService {

    creditorsStaticArray: Creditor[] = [];

    getCreditorsFromAPI() {
        return this.http.get<Creditor[]>(this.creditorsUrl);
      }
}

В вашем компоненте:

 loadedCreditors: Creditor[] = [];

ngOnInit() {
    this.fetchDataService.getCreditorsFromAPI()
        .subscribe(res => this.loadedCreditors = res)

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...