web-dev-qa-db-fra.com

TypeError: vous avez fourni un objet non valide pour lequel un flux était attendu. Vous pouvez fournir un objet Observable, Promise, Array ou Iterable.

J'essaie de map à partir d'un appel de service mais j'obtiens une erreur . Regardé/ subscribe n'est pas défini dans l'angle 2? et il est dit que pour souscrire, nous devons revenir de l'intérieur des opérateurs. J'ai aussi des déclarations de retour.

Voici mon code:

checkLogin(): Observable<boolean> {
    return this.service.getData()
        .map(
            response => {
                this.data = response;                            
                this.checkservice = true;
                return true;
            },
            error => {
                // debugger;
                this.router.navigate(['newpage']);
                console.log(error);
                return false;
            }
        )
        .catch(e => {
            return e;
        });
}

Journal d'erreur:

TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
25
Aakash Thakur

Dans votre exemple de code, votre opérateur map reçoit deux rappels, alors qu'il ne devrait en recevoir qu'un. Vous pouvez déplacer votre code de traitement des erreurs vers votre rappel de capture.

checkLogin():Observable<boolean>{
    return this.service.getData()
                       .map(response => {  
                          this.data = response;                            
                          this.checkservice=true;
                          return true;
                       })
                       .catch(error => {
                          this.router.navigate(['newpage']);
                          console.log(error);
                          return Observable.throw(error);
                       })
   }

Vous devez également importer les opérateurs catch et throw.

import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

EDIT: Notez qu'en renvoyant Observable.throwdans votre gestionnaire catch, vous ne capturez pas réellement l'erreur - elle restera visible sur la console.

14
snorkpete

Dans mon cas, l'erreur s'est produite uniquement lors des tests e2e. Cela est dû à throwError dans mon AuthenticationInterceptor.

Je l'ai importé à partir d'une source incorrecte car j'ai utilisé la fonctionnalité d'importation de WebStorm. J'utilise RxJS 6.2.

Faux:

import { throwError } from 'rjxs/internal/observable/throwError';

Correct:

import { throwError } from 'rjxs';

Voici le code complet de l'intercepteur:

import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const reqWithCredentials = req.clone({withCredentials: true});
    return next.handle(reqWithCredentials)
     .pipe(
        catchError(error => {
          if (error.status === 401 || error.status === 403) {
            // handle error
          }
          return throwError(error);
        })
     );
  }
}
9
Stevy

Vous retournez un observable alors que votre code ne renvoie qu'un booléen. Donc, vous devez utiliser comme ci-dessous

.map(response => <boolean>response.json())

Si vous utilisez un autre service commun checkservice dans votre cas, vous pouvez simplement utiliser 

this.service.getData().subscribe(data=>console.log(data));

Cela rendra votre fonction checkLogin() avec le type de retour nulle.

 checkLogin():void{
      this.service.getData()
            .map(response => {  
                           this.data = response;                            
                           this.checkservice=true;
             }).subscribe(data=>{ });

et vous pouvez utiliser this.checkService pour vérifier votre condition

7
Aravind

Si votre fonction s'attend à renvoyer un booléen, procédez comme suit:

  1. Importation:
import { Observable } from 'rxjs/Observable';
  1. Ensuite
checkLogin(): Observable<boolean>{
    return this.service.getData()
           .map(response => {  
               this.data = response;                            
               this.checkservice=true;
               return true;
           })
           .catch(error => {
               this.router.navigate(['newpage']);
               console.log(error);
               return Observable.of(false);
           })
 }

J'oubliais de rendre l'autre observable dans pipe(switchMap(

this.dataService.getPerson(personId).pipe(
  switchMap(person => {
     //this.dataService.getCompany(person.companyId); // return missing
     return this.dataService.getCompany(person.companyId);
  })
)
2
FindOutIslamNow

J'ai été confronté à ce problème lors de la tentative d'authentification d'un utilisateur à l'aide d'un jeton Web JSON. dans mon cas, c'est lié à l'intercepteur d'authentification.

L'envoi d'une demande d'authentification d'un utilisateur ne nécessite pas de jeton puisqu'il n'existe pas encore.

Vérifiez que votre intercepteur inclut ceci:

if (req.headers.get('No-Auth') == "True")
            return next.handle(req.clone());

Et que vous fournissiez {'No-Auth':'True'} à votre requête d'en-tête comme ceci: 

  authenticateUser(user): Observable<any> {
    const headers = new HttpHeaders({'No-Auth':'True'});
    headers.append('Content-Type', 'application/json');
    return this.httpClient.post(`${this.apiEndpoint}/auth/authenticate`, user, {headers: headers});
  }
1
Badis Merabet

Peut être déclenché par une virgule (,) dans un RxJS pipe(...)

La compilation n'acceptera pas cette virgule supplémentaire à la fin:

pipe(first(), map(result => ({ event: 'completed', result: result}),);

Cela devient un opérateur 'invisible' undefined qui visse tout le tuyau et conduit à un message d'erreur très déroutant - qui dans ce cas n'a rien à voir avec ma logique réelle.

0
Simon_Weaver

J'ai écrit ceci parce que j'arrive ici en cherchant la même erreur et que cela pourrait être utile pour quelqu'un à l'avenir.

Je reçois la même erreur en essayant d'initialiser une variable de service à partir de son constructeur en appelant une API distante via http.get et . Subscribe ()

Après de nombreux tests sans comprendre le problème, je l’ai enfin compris: mon application avait une authentification et un HttpInterceptor, et j’essayais d’initialiser le service en appelant une méthode API publique à l’aide de http. get (...) sans 'No-Auth' en-têtes. Je les ai ajoutés comme ici, et le problème résolu pour moi:

getData() {
var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-urlencoded','No-Auth':'True' });    
return this.http.get(environment.urlApi.Literales, { headers: reqHeader });  
}

Quel mal de tête :(

0
tomasofen

Dans mon cas dans Angular-5, le fichier de service n’était pas importé et j’accédais à la méthode et abonnais les données. Après l’importation du fichier de service, cela fonctionnait parfaitement.

0
Rakesh Pandey

J'ai le même message d'erreur exact pendant que je faisais mon test d'unité et que je levais une exception observable après me moquer de mes services.

Je l'ai résolu en passant la fonction exacte et le format dans Observable.throw.

Code actuel qui appelle le service et subscribe pour obtenir des données. remarquez que catch permet de gérer l’erreur 400.

     this.search(event).catch((e: Response) => {
        if (e.status === 400) {
          console.log(e.json().message);
        } else if (e.url) {
          console.log('HTTP Error: ' + e.status + ' ' + e.statusText,
            'URL: ' + e.url, 'Info: ' + e.json().message));
        }
      }).finally(() => {
        this.loading = false;
      }).subscribe((bData) => {
        this.data = bData;
      });

Le code à l'intérieur du service

  search() {
    return this.someService.getData(request)
       .do((r) => {
          this.someService.defaultHeaders.delete('skipAlert');
          return r;
        })
      .map((r) => {
          return r.businessObjectDataElements.length && r.businessObjectDataElements || null;
        });
  }

Tests unitaires

Je me suis moqué de SomeService et ai renvoyé des données observables et tout est bien car il contient toutes les méthodes requises.

 someServiceApi = fixture.debugElement.injector.get(SomeService);
 spyOn(someServiceApi, 'getData').and.returnValue(Observable.of({}));

Le code ci-dessus est correct, mais lorsque je tentais de tester la condition d'erreur/capture en passant Observable.throw({}), il me montrait l'erreur car il attendait le retour du type Response.

Donc, en dessous du service, le retour moqueur me donnait cette erreur.

someServiceApi.getData
  .and.returnValue(Observable.throw(new Response({status: 400, body: [], message: 'not found error'})));

Donc, je l'ai corrigé en répliquant la fonction exacte attendue dans mon objet de retour, en passant plutôt une valeur de type Response.

someServiceApi.getData
  .and.returnValue(Observable.throw({status: 400, json: () => { return {message: 'not found error'}}, body: []}));
// see `json: () => { return {message: 'not found error'}}` inside return value
0
Aniruddha Das