Reputation: 179
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
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 ofObservable<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,
from
converting promise into Observable and emitting data on promise resole which is a Category type Array(Category[]
)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))
CategoryEnum.disabilities
,I achived this by filter((category: Category) => category.enum === CategoryEnum.disabilities)
.filter
operator will bypass all category which will not satisfy our conditiontoArray
operatorIf 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