How to get an Observable from an array item?

Asked

Viewed 1,134 times

3

Working with Observable and Rxjs, I came across the following problem. At a certain point in the code, my access to the bank is done as follows:

getExemplo(id: number):Observable<Exemplo>{
  return this.http.get<Exemplo[]>(PATH)
  // TODO filtrar array dentro do observable para pegar item correto
}

How can I perform a filtration inside that Observable in order to return only the first item whose id is equal to id passed as parameter?

  • 2

    Isn’t it better on the access part of the bank to make that filter already? (I do not know if you have this possibility, it would be good to put, you have dominion or is third party?)

  • It’s more like an experience I’m doing, to learn how to use filters in an Observable

2 answers

6


The idea is to use operations pipe and map, to map the answer to what you need:

import { map } from 'rxjs/operators';

getExemplo(id: number): Observable<Exemplo>{
  return this.http.get<Exemplo[]>(PATH).pipe(
    map(exemplos => exemplos.filter(e => e.id === id)[0])
  );
}

In the case, exemplos is the array of Exemplo, from which you filter the elements by ID.

Just one detail: the method filter returns another array, containing the filtered elements. So to catch the first element you must use [0] soon after, so that the return is Observable<Exemplo> (which is what getExemplo is returning).

If you just use filter (without taking the first element with [0]), the return will be an array, and the result will be an Observable<Exemplo[]>.


Obviously the above code assumes that there will always be an element with the given ID. But if you want, you can also check if filter returned an empty array. And if empty (ie no element with ID found) return null, for example (or take any other action you deem necessary):

getExemplo(id: number): Observable<Exemplo>{
  return this.http.get<Exemplo[]>(PATH).pipe(
    map(exemplos =>  {
      let filtrados = exemplos.filter(e => e.id === id);
      if (filtrados.length > 0) { // tem pelo menos um elemento com o ID
        return filtrados[0]; // retorna o primeiro
      }
      // nenhum elemento com o ID foi encontrado, retorna null
      return null;
    })
  );
}

Using the above code, simply check if the Exemplo returned is null:

getExemplo(123).subscribe(exemplo => {
    if (exemplo) {
        // exemplo com ID 123 existe
    } else {
        // exemplo com ID 123 não existe
    }
}

Another alternative is to use the method find:

getExemplo(id: number): Observable<Exemplo>{
  return this.http.get<Exemplo[]>(PATH).pipe(
    map(exemplos => exemplos.find(e => e.id === id))
  );
}

The find returns the first element of the array that satisfies the condition, or undefined if none is found.

5

You have to map the answer only to the item you want:

 return this.http.get<Exemplo[]>(PATH).pipe(
       map(response => { //map do rxjs
              return response.filter(item=>item.id===id); // filter do array nativo
      })
 )
  • I think you should change the type of return too, since now only returns one object, would be: return this.http.get<Exemplo>(PATH) and the rest of the code you placed.

  • I think you’re right because this guy is about the get and not what happens after the pipe

  • Oh yes. It makes sense. You’re right.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.