Search code examples
javascriptangularrxjsobservable

subscriber.next() is not firing after subscriber.error statement


Based on the input data I want to decide whether it is valid data or not and send the observable to the to end.

I have tried to create a observable and sequential subscribe.next() is working correctly but any error is coming then after that no statement is working.

const observable = new Observable((subscriber) => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.error('failed this after second');
  subscriber.next(3);
  subscriber.next(4);
  subscriber.complete();
});

observable.subscribe({
  next(x) {
    console.log('got value ' + x);
  },
  error(err) {
    console.error('something wrong occurred: ' + err);
  },
  complete() {
    console.log('done');
  },
});

Current output:

  • got value 1
  • got value 2
  • something wrong occurred: failed this after second

Expected output

  • got value 1
  • got value 2
  • something wrong occurred: failed this after second
  • got value 3
  • got value 4
  • done

Here is the stackblitz link https://stackblitz.com/edit/zlksm5?devtoolsheight=50&file=index.ts


Solution

  • The Observable Contract

    OnError:

    • Indicates that the Observable has terminated with a specified error condition and that it will be emitting no further items

    Emphasis mine.

    If you want something that keeps going after it completes, you don't want an observable.

    Toward a solution

    Just emit your error as a value. You could (for example) wrap your emissions in RxJS Notification objects so that you can materialize or dematerialize observables and keep a consistent API of emissions.

    For example:

    const observable = new Observable(subscriber => {
      subscriber.next({ kind: "N", value: 1 });
      subscriber.next({ kind: "N", value: 2 });
      subscriber.next({ kind: "E", error: new Error("failed this after second") });
      subscriber.next({ kind: "N", value: 3 });
      subscriber.next({ kind: "N", value: 4 });
      subscriber.next({ kind: "C" });
      subscriber.complete();
    });
    
    /**** Alternative written more succinctly ****/
    
    const observable = of(
      { kind: "N", value: 1 },
      { kind: "N", value: 2 },
      { kind: "E", error: new Error("failed this after second") },
      { kind: "N", value: 3 },
      { kind: "N", value: 4 },
      { kind: "C" }
    );
    
    
    observable.subscribe((notification) => {
      switch (notification.kind) {
        case "N":
          console.log("got value ", notification.value);
          break;
        case "E":
          console.error("something wrong occurred: ", notification.error.message);
          break;
        case "C":
          console.log("done");
      }
    });