1
votes

I have this code :

const id = 1; // id = 2

of([{id: 1, name: 'abc'}]).pipe(
            map(items => items.find(item => item.id === id)),
            switchMap(item => item ? of(item) : this.makeHttpRequest(id))
        );

makeHttpRequest(id: number): Observable<IdNamePair>{}

in short,

  • if object with specific id is found in array, return observable of({id: 1, name: 'abc'})

  • if object not found in array, return observable returned by
    this.makeHttpRequest(id) method

I want to eliminate the of(item) operator.

This code works but is there a way without creating a new observable and reusing the one created by "map()" ?

edit:

export class MyService {
    private _list = new BehaviorSubject([{id: 1, name: 'abc'}]);
    list = this._list.asObservable();

    findOne(id: number) {
        this.list.pipe(
                    map(items => items.find(item => item.id === id)),
                    switchMap(item => item ? of(item) : this.makeHttpRequest(id))
                );
    }
}

in Angular component :

export class MyComponent {

    item$: Observable<IdNamePair>;

    constructor(private service: MyService) {}

    ngOnInit() {
            this.item$ = this.service.findOne(1); // or (2), id comes from router
    }
}
1
I do not think there is. The function passed in switchMap as parameter has to return an Observable. In the case of item null, this is performed by this.makeHttpRequest(id). In the other case you have to find a way to create an Observable, and of seems the most natural way. - Picci
you want to implement a sort of cache if I understand. So if you already have the element you don't fetch it. In this case create your observable from the 'cahce' maybe is not the best aproach. you'r event should be the id you pass not the list you try to filter. If I'm in the right drection I can help you with an implementation - rick
You have two of()s so which one you want to get rid of? - martin
You could do it without of. For example from coupled with filter, but you would wait for completion, for example using toArray. The point is, the solution would be more complicated and not necessarily elegant. - madjaoue
@martin, the second "of()" inside the switchMap operator. I'm looking for something like an "else()" operator. There's an "iif()" operator, but that doesn't solve the problem. - Wolf359

1 Answers

0
votes

You can

const id = 1; // id = 2

const [hasItem, noItem] = of([{id: 1, name: 'abc'}]).pipe(
            map(items => items.find(item => item.id === id)),
            partition(Boolean)
        );

const res = merge(hasItem, noItem.pipe(switchMapTo(this.makeHttpRequest(id))