-1

In my Angular13 component I have an observable sending out a stream of data.

I want to do some data manipulation of this data outside of the Observable.

    myObservable$: Observable<ReadonlyArray<MyObject>> = this.store.select( get it from global ngrx store )
    globalArray: Array<MyObject> = [];


    ngOnInit(): void {

    this.myObservable$.subscribe(x => {
          let results = x.reduce((accum: any, item: MyObject) => {
            // does some data manipulation reduce stuff
          }, {});

          console.log(`results is ...`, results);
          
          this.globalArray = results;               // Does not work, globalArray remains blank.
          
          this.globalArray.push(results)            // Does not work, I get a global array with a blank first entry and then 2 other entries containing ALL the data.
          
         });
         
         
    // I want to do stuff to globalArray here, outside of the Observable
    // modify it's data quite a bit more
    // have other components use it as a data source.

    }

Also if I try to just make the global array equal the observable I get another error:

    // Error: Type 'Subscription' is missing the following properties from type MyObject: : length, pop, push, concat, and 28 more
    this.globalArray = this.myObservable$.subscribe(x => {
          let results = x.reduce((accum: any, item: MyObject) => {
            // does some data manipulation reduce stuff
          }, {});
          
          return results;

         });

Any help appreciated! I feel that I must be working with Observables the wrong way? This is probably a masterclass of how not to use observables.

Scottish Smile
  • 455
  • 7
  • 22
  • If you want to modify data AFTER your reduce operation you can't do it outside subscription, you have to use pipe() function and use mergeMap or switchMap to process data. Can post your entire code and explain which functions are involved in that array? – Marc Guillem Apr 20 '23 at 10:25

2 Answers2

0

Observable.subscribe() returns a Subscription which is just a way to be able to cancel your data stream.

Normally I'd recommend you do something like this...

  globalArray$: Observable<MyObject[]>;
  private destroy$: Subject<void> = new Subject();

  ngOnInit(): void {
    this.globalArray$ = this.store.select( get it from global ngrx store ).pipe(
      map(x => x.reduce(
        (accum: any, item: MyObject) => {
          // does some data manipulation reduce stuff
        },
        {}
      ),
      // Remove this when done debugging
      tap(x => console.log(
        'globalArray$ emit',
        JSON.parse(JSON.stringify(x)) // see https://developer.mozilla.org/en-US/docs/Web/API/Console/log
      )),
      // when this service is destroyed, close the data stream
      takeUntil(this.destroy$),
      // don't repeat all this per downstream subscriber, and when something subscribes, start with the last-emitted
      shareReplay(1)
    );
  }

  ngOnDestroy() {
    const d$ = this.destroy$;
    if (d$) {
      d$.next();
      d$.complete();
    }
  }

However, you're already using ngrx! You should use ngrx in the way it's meant to be used by creating a selector and all the components leverage that, instead!

JSmart523
  • 2,069
  • 1
  • 7
  • 17
0

ok if its comming

  this.globalArray = this.myObservable$.subscribe(x => {
      let results = x.reduce((accum: any, item: MyObject) => {
        // does some data manipulation reduce stuff
      }, {});
      
      return results;

     });