угловая загрузка локального файла, затем сделать http-вызовы, чтобы вернуть наблюдаемые - PullRequest
0 голосов
/ 02 ноября 2018

Я новичок в Angular, JS и наблюдаемых. У меня есть класс машинописи под названием DataService. Я хочу, чтобы он загружал список URL-адресов из локального файла в формате JSON, а затем каким-то образом вызывал эти URL-адреса (для нескольких API REST) ​​и возвращал наблюдаемые. Проблема в том, что мой код не ждет загрузки файла конфигурации, прежде чем будут вызваны функции REST API.

Я подумал, что конструктор DataService мог бы загрузить файл конфигурации, а затем иметь уникальные функции для каждого вызова API REST, но это не работает

мой код:

export class DataService {

  configFile

  constructor(private http: HttpClient) {
    this.http.get('/assets/restApiUrlListConfig.json').subscribe(config => {
      this.configFile = config;
    });
  }

  getUrlFromConfigFile(name: string): string {
    ...
      this returns the URL from the config file
    ...
  }

  getUrlAData(): Observable {
    return this.http.get( getUrlFromConfigFile('A') )
  }

}

Мои другие компоненты имеют такой код:

export class SomeComponent implements OnInit {

someComponentAData

constructor(private data: DataService) { }

ngOnInit() {
    this.data.getUrlAData().subscribe(
        data => {
            this.someComponentAData = data
        }
    )
}

Я получаю сообщение об ошибке, что наблюдаемое, возвращаемое из службы данных, не определено. Я верю в то, что конструктор еще не завершил загрузку файла конфигурации, и я думаю, что функция getUrlAData ничего не возвращает.

Мне кажется, что я не правильно обрабатываю эти асинхронные вызовы, но я не знаю, как сообщить свой код:

  1. создать объект службы данных
  2. загрузить файл данных, прежде чем что-либо еще можно сделать
  3. позволяет асинхронно вызывать другие функции ПОСЛЕ загрузки файла конфигурации

Угловой CLI: 6.2.3
Узел: 8.12.0
ОС: win32 x64
Угловой: 6.1.8

Редактировать 1: попытка реализовать предложенное решение

My DataService

  configFile
  configObservable: Observable<any>;
  someSubscribeObj

  constructor(private http: HttpClient) {

    this.someSubscribeObj = this.http.get('/assets/restApiUrlListConfig.json').subscribe(config => {
      this.someSubscribeObj = undefined;
      this.configFile = config;
    });

  }

  getObsFromConfigFile(name: string): Observable<any> {
    //...
    if (this.configFile != undefined) {
      console.log('this.restApiUrlListConfig[name]',this.configFile[name])
      return of(this.configFile[name])
    }
    else
      return of(this.someSubscribeObj.pipe(map(c => c[name]))) 
      //this.configObservable
    //...
  }


  getUrlAData(): Observable<any> {
    return this.getObsFromConfigFile('A').pipe(mergeMap(url => this.http.get(url)))
  }

Мой другой компонент:

  constructor( private data: DataService ) { }

  ngOnInit() {

    //this.data.loggedIn.pipe((p) => p);

    this.data.getUrlAData().subscribe(
      data => {
        this.urlAData = data
      }
    )
}

Мне не удалось сохранить «подписку» в наблюдаемой, поэтому я создал универсальный тип varable любого типа, но во время выполнения у меня возникает проблема с командой pipe:

TypeError: this.someSubscribeObj.pipe не является функцией в DataService.push ../ src / app / services / data.service.ts.DataService.getObsFromConfigFile (data.service.ts: 67) в DataService.push ../ src / app / services / data.service.ts.DataService.getUrlAData (data.service.ts: 74)

Редактировать 2: неудачный обходной путь

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

http.get(config_file_url).subscribe( 
config => { 
http.get( config['A'] ).subscribe( adata => { do things }; 
http.get config['B'].subscribe( bdata => {do things };
}
)

Я чувствую, что должен иметь возможность использовать какую-то MergeMap, но я не мог заставить их работать так, как я думал.

1 Ответ

0 голосов
/ 02 ноября 2018

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

export class DataService {

  configFile
  configObservable: Observable<any>;

  constructor(private http: HttpClient) {
    this.configObservable = this.http.get('/assets/restApiUrlListConfig.json').pipe(
      map(config => {
        this.configObservable = undefined;
        this.configFile = config;
        return configFile;
      })
      );
  }

  getUrlFromConfigFile(name: string): Observable<string> {
    ...
      return of(configFile[name]) if configFile is set else return configObservable.pipe(map(c => c[name]));
    ...
  }

  getUrlAData(): Observable<string> {
    return this.getUrlFromConfigFile('A').pipe(map(url => this.http.get(url)))
  }

}

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

...