TypeError: вы указали недопустимый объект, в котором ожидался поток. Вы можете предоставить Наблюдаемый, Обещающий, Массив или Итерабельный
Я пытаюсь выполнить map
из вызова службы, но получаю сообщение об ошибке.
Посмотрел подписка не определена в angular 2?, и он сказал, что для того, чтобы подписаться, нам нужно вернуться изнутри операторов. У меня также есть операторы return.
Здесь мой код:
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;
});
}
Журнал ошибок:
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
Ответы
Ответ 1
В вашем примере кода у вас есть оператор map
, получающий два обратных вызова, когда он должен получать только один. Вы можете переместить код обработки ошибок на ваш обратный вызов catch.
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);
})
}
Вам также необходимо импортировать операторы catch
и throw
.
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
EDIT:
Обратите внимание, что, возвращая Observable.throw
в ваш обработчик catch, вы фактически не поймаете ошибку - она все равно будет отображаться на консоли.
Ответ 2
В моем случае ошибка произошла только во время тестов e2e. Это было вызвано throwError
в моем AuthenticationInterceptor.
Я импортировал его из неправильного источника, потому что использовал функцию импорта WebStorm. Я использую RxJS 6.2.
Неправильно:
import { throwError } from 'rjxs/internal/observable/throwError';
Правильный:
import { throwError } from 'rjxs';
Вот полный код перехватчика:
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);
})
);
}
}
Ответ 3
Вы возвращаете Observable, где, когда ваш код возвращает только логическое значение. Поэтому вам нужно использовать, как показано ниже
.map(response => <boolean>response.json())
Если вы используете другую общую службу checkservice
в своем случае, вы можете просто использовать
this.service.getData().subscribe(data=>console.log(data));
Это сделает вашу функцию checkLogin()
с возвращаемым типом как void
checkLogin():void{
this.service.getData()
.map(response => {
this.data = response;
this.checkservice=true;
}).subscribe(data=>{ });
и вы можете использовать this.checkService
для проверки вашего состояния
Ответ 4
Если ваша функция ожидает возврата логического значения, просто сделайте это:
- Импортировать:
import { of, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
- затем
checkLogin(): Observable<boolean> {
return this.service.getData()
.pipe(
map(response => {
this.data = response;
this.checkservice = true;
return true;
}),
catchError(error => {
this.router.navigate(['newpage']);
console.log(error);
return of(false);
})
)}
Ответ 5
Я столкнулся с этой проблемой при попытке аутентификации пользователя с помощью веб-токена JSON. в моем случае это связано с перехватчиком аутентификации.
Отправка запроса на аутентификацию пользователя не должна предоставлять токен, так как он еще не существует.
Убедитесь, что ваш перехватчик включает это:
if (req.headers.get('No-Auth') == "True")
return next.handle(req.clone());
И что вы предоставляете {'No-Auth':'True'}
для вашего запроса заголовка следующим образом:
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});
}
Ответ 6
Может быть вызвано случайной запятой (,
) в канале RxJS pipe(...)
Компиляция не поймает эту дополнительную запятую в конце:
pipe(first(), map(result => ({ event: 'completed', result: result}),);
Он становится "невидимым" undefined
оператором, который запутывает весь канал и приводит к очень запутанному сообщению об ошибке, которое в данном случае не имеет ничего общего с моей реальной логикой.
Ответ 7
Я написал это, потому что приехал сюда в поисках той же ошибки, и это может пригодиться кому-то в будущем.
Я получаю ту же ошибку при попытке инициализировать переменную службы из ее конструктора, вызывая удаленный API через http.get и .subscribe()
После многих тестов, не понимая, в чем проблема, я наконец-то понял: у моего приложения была аутентификация и HttpInterceptor, и я пытался инициализировать сервис, вызывающий метод публичного API, используя http.get(...) без 'No-Auth Заголовки. Я добавил их как здесь, и проблема для меня решена:
getData() {
var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-urlencoded','No-Auth':'True' });
return this.http.get(environment.urlApi.Literales, { headers: reqHeader });
}
Что за головная боль :(
Ответ 8
В моем случае в Angular-5 сервисный файл не был импортирован, из которого я получал доступ к методу и подписывал данные. После импорта сервисного файла он работал нормально.
Ответ 9
Я забыл вернуть другой наблюдаемый в pipe(switchMap(
this.dataService.getPerson(personId).pipe(
switchMap(person => {
//this.dataService.getCompany(person.companyId); // return missing
return this.dataService.getCompany(person.companyId);
})
)
Ответ 10
У меня есть то же сообщение об ошибке, когда я выполнял мой unit test и бросая наблюдаемое исключение после издевательства над моими услугами.
Я разрешил его, передав точную функцию и формат внутри Observable.throw
.
Фактический код, вызывающий службу, и subscribe
для получения данных. обратите внимание, что catch
обрабатывает ошибку 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;
});
Код внутри службы
search() {
return this.someService.getData(request)
.do((r) => {
this.someService.defaultHeaders.delete('skipAlert');
return r;
})
.map((r) => {
return r.businessObjectDataElements.length && r.businessObjectDataElements || null;
});
}
Тестирование устройств
Я высмеивал SomeService и возвращаю наблюдаемые данные и их штраф, поскольку в нем есть все необходимые методы.
someServiceApi = fixture.debugElement.injector.get(SomeService);
spyOn(someServiceApi, 'getData').and.returnValue(Observable.of({}));
Вышеприведенный код является okey, но когда я пытался проверить условие catch/error, передав Observable.throw({})
, он показывал мне ошибку, так как ожидал возвращения типа Response
из службы.
Таким образом, ниже насмешливое возвращение службы дало мне эту ошибку.
someServiceApi.getData
.and.returnValue(Observable.throw(new Response({status: 400, body: [], message: 'not found error'})));
Итак, я исправил его, реплицируя точную ожидаемую функцию в моем возвращаемом объекте, скорее передав значение типа 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