Paulo Henrique Junior
Paulo Henrique Junior

Reputation: 179

Trying to work with one observable inside another

import './style.css';

import { of, map, Observable, from, iif } from 'rxjs';
import { switchMap } from 'rxjs/operators';

export class Category {
  name: string;
  id: number;
  enum: CategoryEnum;

  constructor(_id: number, _name: string, _categoryEnum) {
    this.name = _name;
    this.id = _id;
    this.enum = _categoryEnum;
  }
}

export const enum CategoryEnum {
  disabilities = 'disabilities',
  gender = 'gender',
}

const examplePromise = new Promise((resolve, reject) => {
  return resolve([
    new Category(1, 'Male', CategoryEnum.gender),
    new Category(2, 'Female', CategoryEnum.gender),
    new Category(3, 'Wheelchair', CategoryEnum.disabilities),
    new Category(4, 'Blind', CategoryEnum.disabilities),
  ]);
});

const observable$: Observable<Category[]> = from(examplePromise);

const result = [];

const returnData = (): Observable<any[]> => {
  let categories$: Observable<CategoryEnum[]> = of([CategoryEnum.disabilities]);

  let result: Category[] = [];

  return categories$.pipe(
    switchMap((category, index) => {
      if (result[category[index]]) {
        result = [...result, result[category[index]]];
      } else {
        observable$.pipe(
          switchMap((data, index) => {
            if (data[index].enum === category[index]) {
              result = [...result, data[index]];
            }

            return of(result);
          })
        );
      }

      return of(result);
    })
  );
};

returnData().subscribe((a) => console.log(a));

Trying to work with one observable inside another to filter categories but not working at all, the return is always an empty array with no data and I needed to return an Observable with an array of categories inside. Any ideas of what is happening with this structure?

Upvotes: 0

Views: 363

Answers (1)

Saptarsi
Saptarsi

Reputation: 878

What I understood from post is that you are trying to filter categories with CategoryEnum.disabilities and you want to receive the result in form of Observable<Category[]>

If it is so,then I would solved it like bellow

From OP,I am considering you are receiving categories in for of Promise<Category[]>

import { Observable, from } from 'rxjs';
import { filter, mergeMap, toArray } from 'rxjs/operators';

export class Category {
  name: string;
  id: number;
  enum: CategoryEnum;

  constructor(_id: number, _name: string, _categoryEnum) {
    this.name = _name;
    this.id = _id;
    this.enum = _categoryEnum;
  }
}

export const enum CategoryEnum {
  disabilities = 'disabilities',
  gender = 'gender',
}

const examplePromise = new Promise((resolve, reject) => {
  resolve([
    new Category(1, 'Male', CategoryEnum.gender),
    new Category(2, 'Female', CategoryEnum.gender),
    new Category(3, 'Wheelchair', CategoryEnum.disabilities),
    new Category(4, 'Blind', CategoryEnum.disabilities),
  ]);
});

const returnData = (): Observable<Category[]> => {
  return from(examplePromise).pipe(
    mergeMap((categories: Category[]) => from(categories)),
    filter((category: Category) => category.enum === CategoryEnum.disabilities),
    toArray()
  );
};

returnData().subscribe(console.log);

So What is happening here,

  • 1st from converting promise into Observable and emitting data on promise resole which is a Category type Array(Category[])
  • Now the task is to emit array data one by one.As we know from operator can do that,so I did this from(categories),but it returns observable,which is here a inner observable,so I had to subscribe it so i did mergeMap((categories: Category[]) => from(categories))
  • Now the above line will emit category one by one
  • 2nd task is to filter categories with CategoryEnum.disabilities,I achived this by filter((category: Category) => category.enum === CategoryEnum.disabilities).filter operator will bypass all category which will not satisfy our condition
  • 3rd job is to accumulate all result in a Array for that i used toArray operator

If creation of source categories is in your hand,then I will suggest you not to wrap categories with promise,by doing this there will be no need to use this line mergeMap((categories: Category[]) => from(categories))

const categories = [
  new Category(1, 'Male', CategoryEnum.gender),
  new Category(2, 'Female', CategoryEnum.gender),
  new Category(3, 'Wheelchair', CategoryEnum.disabilities),
  new Category(4, 'Blind', CategoryEnum.disabilities),
];

const returnData = (): Observable<Category[]> => {
  return from(categories).pipe(
    filter((category: Category) => category.enum === CategoryEnum.disabilities),
    toArray()
  );
};

returnData().subscribe(console.log);

Upvotes: 1

Related Questions