Последовательный вызов вложенной подписки

#angular #rxjs #rxjs6

#angular #rxjs #rxjs6

Вопрос:

вызов одной подписки, которая зависит от другого метода подписки

структура:

     this.example1().subscribe(res => {
      this.response = res;
    })


  example1(): Observable<any> | any {
    this.example2().pipe(
      catchError(err => {
        return throwError(err);
      })
    ).subscribe(res => {
       return of(res);
    });
  }

  example2(): Observable<any> | any {
     this.example3().pipe(
      catchError(err => {
        return throwError(err);
      })
    ).subscribe(res => {
      return of(res);
    });

  }

  example3() {
    return of('return from example 3');
  }
  

теперь появляется ошибка «Не удается прочитать свойство ‘pipe’ из undefined»

example3() возвращает значение правильно, но из example2 значение не возвращается к примеру 1

ссылка: демонстрационная версия stackblitz

Комментарии:

1. example2() ничего не возвращает.

2. ни то, ни другое не example1()

3. @denajan, когда наблюдаемый объект зависит от другого, вы должны использовать switchMap

4. привет, я вернул значение из example1 () и example2 (). Но все еще безуспешно

Ответ №1:

example1() и example2() функции ничего не возвращают. Просто добавьте ключевое слово return, чтобы вернуть ваши наблюдаемые.

Ответ №2:

Вам не нужно подписываться в example1(), example2(), example3().
Возврат в методе асинхронного обратного вызова subscribe не является возвратом функции.

   example1(): Observable<any> | any {
    console.log('1');
    return this.example2().pipe(
      catchError(err => {
        return throwError(err);
      })
    );
  }

  example2(): Observable<any> | any {
    console.log('2');
    return this.example3().pipe(
      catchError(err => {
        return throwError(err);
      })
    );
  }

  example3() {
    console.log('3');
    return of('return from example 3');
  }
  

StackBlitz

ОБНОВЛЕНИЕ (15.03.2019) С вашим комментарием код должен быть:

 export class AppComponent {
  response;
  private init$: Observable<any>;

  public ngOnInit() {
    //get Data from remote
    this.example3().subscribe(value => {
      //Do primary somethimg with result
      let calcVal = value *2;
      // Do remote something with data
      this.example2(calcVal).subscribe(newValue => {
        // Result with updated data
        console.log(newValue);
        this.response = newValue;
      });
    });
  }

  // Async do something with data
  example2(value: number): Observable<string>{
    return of('Value is: '   value);
  }

  // Async get data
  example3(): Observable<number> {
    console.log('3');
    return of(3);
  }

}
  

StackBlitz

Или с помощью switchMap:

 export class AppComponent {
  response;
  private init$: Observable<any>;

  public ngOnInit() {
    let obs = this.example3().pipe(switchMap(val => this.example2(val)));
    obs.subscribe(result => this.response = result);
  }

  // Async do something with data
  example2(value: number): Observable<string>{
    return of('Value is: '   value);
  }

  // Async get data
  example3(): Observable<number> {
    console.log('3');
    return of(3);
 
}
  

StackBlitz

Комментарии:

1. спасибо @lvanes за ваш ценный ответ. Это работает нормально, но мой сценарий немного отличается. Я что-то вычисляю в функции sample2, где входящее значение поступает из sample3 (), а конечное значение будет передано в функцию sample1 (). Пожалуйста, посмотрите на stackblitz stackblitz.com/edit/angular-eyz2j7

2. @debanjanMal Должно ли ваше вычисление example2 быть асинхронным? Обновленный пример

3. @lvanes да, это асинхронные данные, но часть вычисления должна выполняться в example2 (), потому что это общее для всех. Я думаю, что могу использовать switchMap

4. switchMap может вам помочь. Но нужно ли вам это? Используется для объединения двух наблюдаемых и автоматической отмены подписки, если первый наблюдаемый поток вызывается next() более одного раза. Ответ (после обновления) вам не подходит? ( О switchMap )

5. @lvanes любое предложение. Это обязательно, вся часть вычисления будет выполняться в example2()