Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

[Sugestão] A API do google retorna ERROR 400 quando "?q=" (vazio) e trava a aplicação, então, fiz uma pequena alteração

Quando utilizamos o BACKSPACE para limpar os dados do FormControl de campoBusca, e, consequentemente, o valor digitado é vazio, o serviço realiza a busca, retornando ERROR 400. Como ainda não temos um tratamento de erro para essa situação, a aplicação TRAVA. Então, resolvi, por enquanto, incluir um null como resposta do Observable.

Em livro.service.ts:

  buscar(valorDigitado: string): Observable<Item[] | **null**> {
    if(valorDigitado) {
      const params = new HttpParams().append('q', valorDigitado);
      return this.http.get<LivrosResultado>(this.API, { params }).pipe(
        map(retorno => {return retorno.items;})
      );
    } else {
     ** return of(null);**
    }
  }

Em lista-livros.component.ts

  campoBusca = new FormControl(); 
  livrosEncontrados$ : Observable<Livro[] | null>;

  /** */
  constructor(private service: LivroService) { }

  /** */
  ngOnInit(): void {
    this.livrosEncontrados$ = this.campoBusca.valueChanges
    .pipe(
      switchMap((valorDigitado) => {return this.service.buscar(valorDigitado)}),
      // tap((items)=>console.log('Retorno da digitação', items)),
      map((items) => { 
        if(items) {
          return this.livrosResultadoParaLivros(items);
        } else {
          **return null;**
        }
      })
    );
  }
4 respostas
solução!

Olá Marcus! Tudo bem contigo?

Entendo a situação que você enfrentou ao lidar com a API do Google e agradeço por compartilhar sua sugestão para resolver o problema de erro 400 e travamento da aplicação. Vamos analisar a alteração que você fez e algumas possíveis melhorias.

Na sua alteração, você modificou o método buscar no arquivo livro.service.ts, incluindo um retorno de null quando o parâmetro valorDigitado é vazio. Essa é uma abordagem válida para evitar o erro 400 quando o campo de busca está vazio. Aqui está o trecho de código modificado:

buscar(valorDigitado: string): Observable<Item[] | null> {
  if (valorDigitado) {
    const params = new HttpParams().append('q', valorDigitado);
    return this.http.get<LivrosResultado>(this.API, { params }).pipe(
      map(retorno => { return retorno.items; })
    );
  } else {
    return of(null);
  }
}

No componente lista-livros.component.ts, você utiliza o FormControl chamado campoBusca para monitorar as mudanças do valor digitado e buscar os livros correspondentes. A observação feita na função ngOnInit() é que, ao receber null na resposta do serviço, você também retorna null. Isso é uma boa prática para evitar erros ao manipular os resultados. Aqui está o trecho de código modificado:

campoBusca = new FormControl();
livrosEncontrados$: Observable<Livro[] | null>;

constructor(private service: LivroService) { }

ngOnInit(): void {
  this.livrosEncontrados$ = this.campoBusca.valueChanges.pipe(
    switchMap((valorDigitado) => { return this.service.buscar(valorDigitado) }),
    map((items) => {
      if (items) {
        return this.livrosResultadoParaLivros(items);
      } else {
        return null;
      }
    })
  );
}

Sua abordagem parece ser funcional, no entanto, considerando que o curso é sobre "RxJS e Angular: programando de forma reativa", podemos otimizar ainda mais a busca usando os recursos do RxJS. Em vez de retornar null, podemos utilizar o operador filter para garantir que a busca só ocorra quando o valor digitado for válido. Além disso, podemos tratar os erros para evitar que a aplicação trave. Vou mostrar essas melhorias no código abaixo:

Em livro.service.ts, vamos ajustar a função buscar:

import { catchError, filter } from 'rxjs/operators';

buscar(valorDigitado: string): Observable<Item[]> {
  if (valorDigitado) {
    const params = new HttpParams().append('q', valorDigitado);
    return this.http.get<LivrosResultado>(this.API, { params }).pipe(
      map(retorno => { return retorno.items; }),
      catchError(error => {
        // Trate o erro de acordo com a sua necessidade, por exemplo:
        console.error('Erro na busca:', error);
        return of([]);
      })
    );
  } else {
    return of([]);
  }
}

E no componente lista-livros.component.ts, vamos fazer a busca somente quando o valor digitado for válido:

import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';

campoBusca = new FormControl();
livrosEncontrados$: Observable<Livro[]>;

constructor(private service: LivroService) { }

ngOnInit(): void {
  this.livrosEncontrados$ = this.campoBusca.valueChanges.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    filter(valorDigitado => !!valorDigitado), // Filtro para buscar apenas quando o valor for válido
    switchMap((valorDigitado) => this.service.buscar(valorDigitado))
  );
}

Com essas alterações, melhoramos a busca reativa e tratamos possíveis erros na solicitação HTTP. Utilizamos os operadores debounceTime, distinctUntilChanged e filter para controlar as solicitações à API e evitar chamadas desnecessárias quando o usuário estiver digitando rapidamente.

Espero ter ajudado! Se tiver mais dúvidas ou precisar de mais esclarecimentos, fique à vontade para perguntar.

Abraços e bons estudos!

Adorei o "filter(valorDigitado => !!valorDigitado)", solução elegante!!!

Putz, realmente: "return of([]);" é bem mais coerente, não precisa redefinir os tipos!!! Obrigado Renan!!!

Opa Marcus! Eaí tudo ok?

Eu fico feliz que você gostou das sugestões.

Obrigado pelos elogios, e parabéns pelo projeto tá, seu código está ótimo também tá bom ;)

Abraços, sucesso em sua carreira e bom estudos.