Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to map from a service call but getting an error. Looked at subscribe is not defined in angular 2? and it said that in order to subscribe we need to return from inside the operators. I have return statements as well.

Here's my 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;     }); } 

Error log:

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

like image 390
Aakash Thakur Avatar asked Apr 21 '17 17:04

Aakash Thakur


2 Answers

In my case the error occurred only during e2e tests. It was caused by throwError in my AuthenticationInterceptor.

I imported it from a wrong source because I used WebStorm's import feature. I am using RxJS 6.2.

Wrong:

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

Correct:

import { throwError } from 'rxjs'; 

Here the full code of the interceptor:

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);         })      );   } } 
like image 63
Stevy Avatar answered Oct 05 '22 17:10

Stevy


In your example code, you have your map operator receiving two callbacks, when it should only be receiving one. You can move your error handling code to your catch callback.

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);                        })    } 

You'll need to also import the catch and throw operators.

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

EDIT: Note that by returning Observable.throwin your catch handler, you won't actually capture the error - it will still surface to the console.

like image 24
snorkpete Avatar answered Oct 05 '22 18:10

snorkpete