Angular вызвать ту же услугу в подписку - PullRequest
1 голос
/ 07 апреля 2020

Какой лучший способ вызвать подписку, дождаться результата, чтобы начать другую подписку? Что-то похожее на ожидание в javascript, мне нужен результат первого вызова, чтобы начать следующий вызов. У меня так:

this.apiService.getAllData()
            .subscribe(
                ( response: any ) => {

                        this.allData = response['data'];
                        this.allData.forEach(function (id) {
                            this.apiService.getDataDetail(id)
                                .subscribe((detail: any) => {
                                    console.log('detail: ', detail);
                                });
                        });
                },
                err => {
                    console.log('Something wrong...');
                }
            );

Моя проблема в том, что подписка на вызовы внутри первой подписки не распознает услугу. Это предупреждение покажет мне мой редактор

Potentially invalid reference access to a class field via 'this.' of a nested function 

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Если я понимаю, что вы пытаетесь выполнить sh:

  • Загрузить все данные из API
  • Затем загрузите каждую отдельную запись из API (используя данные, которые вы получили из первого запроса API)

Для этого вам понадобится оператор switchMap() и, вероятно, forkJoin() или combineLatest() функций.

/* needed imports */
import { combineLatest, forkJoin } from 'rxjs';
import { tap, switchMap } from 'rxjs/operators';

/* load all data */
this.apiService.getAllData().pipe(

  /* switchMap will "switch" the observable your subscriber receives */
  switchMap((response: any) => {
    this.allData = response['data'];

    /* we will map allData to an observables (ie: api requests) */
    /* try using an arrow function here to avoid `this` conflicts */
    const arrayOfObservables = this.allData.map(data => {
      return this.apiService.getDataDetail(id).pipe(
        tap(detail => console.log('detail: ', detail))
      );
    });

    /* switchMap needs to return an observable */
    return forkJoin(arrayOfObservables); 
    // could also use combineLatest(arrayOfObservables)
  })
).subscribe(
  (data: any[]) => {
    /* important to note that data will be an array of all the 
      individual details received from the api */
    console.log('received data: ', data);
  },
  err => console.log('Something wrong...', err)
);

Важно отметить, что forkJoin не будет выдавать значение до тех пор, пока все не обнаружат наблюдаемые в массиве завершить . Это, вероятно, ваше желаемое поведение, так как вы делаете http-запросы, которые всегда выполняются, если вы используете Angular.

Если вы хотите, чтобы данные вашего подписчика передавались по мере их поступления, а не по завершении всех, тогда вам может понадобиться что-то вроде mergeMap(). Это более сложно, и не похоже, что это то, что вы хотите здесь (хотя я могу ошибаться).

РЕДАКТИРОВАТЬ: См. Мой ответ здесь для примера mergeMap / concatMap, чтобы показать, как его реализовать. Мой ответ также касается видимой очистки, чтобы избежать утечек памяти.

1 голос
/ 07 апреля 2020

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

this.apiService.getAllData()
            .subscribe(
                ( response: any ) => {

                        this.allData = response['data'];
                        that = this
                        that.allData.forEach(function (id) {
                            that.apiService.getDataDetail(id)
                                .subscribe((detail: any) => {
                                    console.log('detail: ', detail);
                                });
                        });
                },
                err => {
                    console.log('Something wrong...');
                }
            );

Вы должны предпочесть другие методы, чем это.

1 голос
/ 07 апреля 2020

Вы можете использовать RX JS для этого. Есть звонок оператора. Карта коммутатора

this.apiService.getAllData()
  .pipe(
    switchMap(( response: any ) => {

                        this.allData = response['data'];
                        this.allData.forEach(function (id) {
                            this.apiService.getDataDetail(id)
                                .subscribe((detail: any) => {
                                    console.log('detail: ', detail);
                                });
                        });
                },
                err => {
                    console.log('Something wrong...');
                })
  )
  .subscribe();

, получить более подробную информацию от https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap. И есть много операторов RX JS, и вы можете легко работать с реактивным программированием, используя эти

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