fransyozef
fransyozef

Reputation: 574

angular rxjs pipe remove element from array

I have a service with a delete function. The delete function will call an api and it will return true or false. When true, I will lookup the index in my array, splice it and return the new array. So for example

private items = [];
onItemDeleted  = new Subject<any>();

  delete(id:number): Observable<any> {
    return this.http.delete('http://my.api.com/item/' + id)
      .pipe(
        switchMap(checkServerSuccessResponse),
        map(data => {
            const index1  = this.items.findIndex((element) => {
              return element.id === id;
            });
            if (index1 >= 0 ) {
              this.items.splice(index1,1);
            }
            this.onItemDeleted.next(this.items);
            return this.items;
          }
        ),
        catchError(returnFalse),
      );
  }

I have a helper for the switchmap :

export function checkServerSuccessResponse(data: Response): Observable<any> {
    return (data && data['success'] === true) ? of(data) : throwError("server responded false");
}

Although this works, I have a feeling the map section can reformatted. I first thought of filter (after the switchmap) to exclude the element with the id I've supplied, then emit the new array, but then I realised, the filter is not subscribed to the this.items array.

What would be the best approach to do this?

Upvotes: 2

Views: 9047

Answers (1)

muradm
muradm

Reputation: 2053

I don't know you other code, for example where this.items coming from, why do you publish updated items to onItemDeleted. But I would probably: a) pass this.items to delete method also like delete(id, items) because on the time when response will arrive, you don't know what will happen with this.items; b) that thing within the map, move to separate function, that will be removeById(items, id); c) simplify pipe. Like this:

private items = [];
onItemDeleted  = new Subject<any>();

  removeById(fromItems, id) {
    const index1  = fromItems.findIndex((element) => {
      return element.id === id;
    });
    if (index1 >= 0 ) {
      fromItems.splice(index1,1);
    }
    return fromItems;
  }

  // who ever calls this, should provide copy of items also
  // then you will be kinda protected from concurrent
  // modification, when http response complete, but this.items
  // is completely different, from when http request started
  delete(fromItems, id:number): Observable<any> {
    return this.http.delete('http://my.api.com/item/' + id)
      .pipe(
        switchMap(checkServerSuccessResponse),
        map(data => this.removeById(fromItems, id)),
        tap(items => this.onItemDeleted.next(items)),
        catchError(returnFalse),
      );
  }

Upvotes: 1

Related Questions