angular - create - TypeError: proporcionó un objeto no válido donde se esperaba una transmisión. Puedes proporcionar un Observable, Promise, Array o Iterable
rxjs (6)
En mi caso, el error ocurrió solo durante las pruebas e2e. Fue causado por throwError
en mi AuthenticationInterceptor.
Lo importé de una fuente incorrecta porque usé la función de importación de WebStorm. Estoy usando RxJS 6.2.
Incorrecto:
import { throwError } from ''rjxs/internal/observable/throwError'';
Correcto:
import { throwError } from ''rjxs'';
Aquí el código completo del 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);
})
);
}
}
Estoy tratando de map
una llamada de servicio pero obtengo un error. Mirado en suscripción no está definido en angular 2? y dijo que para suscribirnos debemos regresar desde dentro de los operadores. Tengo declaraciones de devolución también.
Aquí está mi código:
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;
});
}
Registro de errores:
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
En su código de ejemplo, su operador de map
recibe dos devoluciones de llamada, cuando solo debería recibir una. Puede mover su código de manejo de errores a su devolución de llamada de captura.
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);
})
}
También necesitarás importar los operadores de catch
y throw
.
import ''rxjs/add/operator/catch'';
import ''rxjs/add/observable/throw'';
EDITAR: tenga en cuenta que al devolver Observable.throw
en el controlador de capturas, no capturará realmente el error; seguirá apareciendo en la consola.
He estado enfrentando este problema al intentar autenticar a un usuario usando el token web JSON. En mi caso está relacionado con el interceptor de autenticación.
El envío de una solicitud para autenticar a un usuario no tiene que proporcionar un token, ya que aún no existe.
Comprueba que tu interceptor incluya esto:
if (req.headers.get(''No-Auth'') == "True")
return next.handle(req.clone());
Y que proporcione {''No-Auth'':''True''}
a la solicitud de su encabezado de esta manera:
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});
}
Si su función espera devolver un booleano, simplemente haga esto:
- Importar:
import { Observable } from ''rxjs/Observable'';
- Entonces
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);
})
}
Tengo el mismo mensaje de error exacto mientras estaba haciendo mi prueba de unidad y lanzando una excepción observable después de burlarme de mis servicios.
Lo resolví pasando la función y el formato exactos dentro de Observable.throw
.
Código real que llama al servicio y se subscribe
para obtener datos. Observa que catch
para manejar el error 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;
});
El código dentro del servicio.
search() {
return this.someService.getData(request)
.do((r) => {
this.someService.defaultHeaders.delete(''skipAlert'');
return r;
})
.map((r) => {
return r.businessObjectDataElements.length && r.businessObjectDataElements || null;
});
}
Examen de la unidad
Me he burlado de SomeService y devolví datos observables y está bien, ya que tiene todos los métodos necesarios en su interior.
someServiceApi = fixture.debugElement.injector.get(SomeService);
spyOn(someServiceApi, ''getData'').and.returnValue(Observable.of({}));
El código anterior es okey pero cuando intenté probar la condición de captura / error al pasar Observable.throw({})
me estaba mostrando el error porque esperaba que el servicio Response
tipo de Response
.
Así que debajo del servicio, el retorno de burla me estaba dando ese error.
someServiceApi.getData
.and.returnValue(Observable.throw(new Response({status: 400, body: [], message: ''not found error''})));
Así que lo corregí al replicar la función exacta esperada en mi objeto de retorno en lugar de pasar un valor de tipo 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
Usted está devolviendo un Observable en donde su código solo devuelve un booleano. Por lo que necesita utilizar como abajo
.map(response => <boolean>response.json())
Si está utilizando otro servicio de checkservice
servicio común en su caso, simplemente puede usar
this.service.getData().subscribe(data=>console.log(data));
Esto hará que su función checkLogin()
con el tipo de retorno sea nula
checkLogin():void{
this.service.getData()
.map(response => {
this.data = response;
this.checkservice=true;
}).subscribe(data=>{ });
y puede utilizar this.checkService
para verificar su condición