订阅回调内的javascript错误

时间:2018-10-05 10:23:25

标签: javascript angular typescript rxjs

  • 我有一个组件A,我将使用behaviourSubject从其中向组件B广播数据,其中每次在组件B中的按钮上单击一次都会在组件B中触发一个http请求。
  • 在组件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;
  }

}

现在可以说组件B中的订阅中发生某种方式的js错误(可能是无法读取未定义的属性“ 0”),然后我的进一步javascript执行停止,并且不侦听后续广播的值。

这是Rxjs的预期行为吗?我该如何处理在订阅块中发生的js错误。

可以在Stackblitz处模拟问题。 最初单击广播按钮,然后您可以看到正在显示的数据。 现在取消注释第38行以模拟问题,然后单击“广播”。它永远不会监听后续呼叫。

1 个答案:

答案 0 :(得分:1)

如果可观察的死亡将其称为错误处理程序,并且它们已关闭,则您无法通过它们发送任何消息,这意味着它们已关闭,包括间隔已死的上游所有内容。

  

如果我们想生活。

隐藏主要观察者链是解决方案
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?