Ошибка JavaScript внутри обратного вызова подписки - PullRequest
0 голосов
/ 05 октября 2018
  • У меня есть компонент A, из которого я передаю данные компоненту B, используя behaviourSubject для моего варианта использования, при котором при каждом нажатии кнопки в компоненте один http-запрос должен запускаться в компоненте B.
  • В компоненте B я подписываюсь на вещание, наблюдаемое из компонента A.

Компонент A:

import { Component, OnInit } from '@angular/core';
import { MessagingService } from '../messaging.service';

@Component({
  selector: 'app-comp-a',
  templateUrl: './comp-a.component.html',
  styleUrls: ['./comp-a.component.css']
})
export class CompAComponent implements OnInit {

  public i= 0;

  constructor(public message: MessagingService) { }

  ngOnInit() {

  }

  broadcast(){
    this.message.broadcast({data:`Broadcasted_${this.i}`});
    this.i++
  }

}

Компонент B:

import { Component, OnInit } from '@angular/core';
import { MessagingService } from '../messaging.service';
import { switchMap } from 'rxjs/operators';
import { of } from 'rxjs';

@Component({
  selector: 'app-comp-b',
  templateUrl: './comp-b.component.html',
  styleUrls: ['./comp-b.component.css']
})
export class CompBComponent implements OnInit {
  public data;
  constructor(public message: MessagingService) {}

  ngOnInit() {
    this.message.getData().pipe(
      switchMap(res => {
        /**
         * here some service call based on brodcasted data.
         * 
         * Lets say service returns json in format 
         * {
         *    data:[{},{}]
         * }
         */
        return of([res.data]);
      })
    ).subscribe(res => {
      /**
               * So in actual use case I will get 
               *  {
               *   data:[{},{}]
               *  }
               * in subscription.
               *
               *  now lets assume sometime I get data as null and i tried to access it as res.data[0].some_property
     then it will throw js error Cannot read property '0' of undefined so subscription breaks and doesnt complete and stops. and then after subsequent broadcast from comp A doesnt triggers subscription in comp B.. is it expected behaviour?
               */

      // let a = this.data[0] //this is delibrate error to simulate my realtime issue
      this.data = res
    }, (error) => {
      console.log("Error happened" + error)
    }, () => {
      console.log("the subscription is completed")
    })
  }

}

Сервис:

import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs';
@Injectable()
export class MessagingService {

  /**
   * Subject to notify the offer console
   */

  private _change_in_year_month = new BehaviorSubject<any>({ data:'old data' });
  public change_in_year_month = this._change_in_year_month.asObservable();

  constructor() { }

  /**
   *
   * @param data  data contains either year or (year and month)
   * This method will broadcast data to offer console to execute service call
   */
  broadcast(data) {
    this._change_in_year_month.next(data);
  }

  /**
   * Method will return observable of Subject which can be subscribed in
   * offer console component to execute service call
   */
  getData() {
    return this.change_in_year_month;
  }

}

Теперь давайте скажем, что каким-то образом произошла ошибка js (может быть «Невозможно прочитать свойство« 0 »из неопределенного») в подписке в Компоненте B, тогда мое дальнейшее выполнение javascript прекращается и не прослушивает последующие передаваемые значения.

Это ожидаемое поведение Rxjs.Как мне обработать ошибку js, возникающую в блоке подписки.

Проблема может быть смоделирована на Stackblitz .Сначала нажмите на кнопку широковещания, затем вы увидите отображаемые данные.Теперь раскомментируйте строку 38, чтобы смоделировать проблему, и нажмите на трансляцию.Он никогда не будет прослушивать последующие звонки.

1 Ответ

0 голосов
/ 05 октября 2018

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

что если мыхочу жить.

решение главной цепочки наблюдателей - это решение
помещать улов в switchmap всякий раз, когда выполняется запрос switchmap создает наблюдаемый ajax, и на этот раз с catch.
switchMap() все равно, завершен ли внутренний Observable, он завершится только после завершения внешнего Observable.Несмотря на то, что внутренняя цепь Observable умирает, внешняя цепь Observable остается активной, потому что обработчик ошибок не был вызван для внешней Observable цепочки.
пример

switchMap((value)=>this.http.get('url' + value).pipe(catchError(() => {return empty()}))
            ))

How to keep an Observable alive after Error in Angular?

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