TypeError: Вы указали недопустимый объект, где ожидался поток. Вы можете предоставить Observable, Promise, Array или Iterable
Я пытаюсь map
из сервисного звонка, но получаю ошибку. Посмотрел подписаться не определяется в угловых 2? и он сказал, что для того, чтобы подписаться, нам нужно вернуться изнутри операторов. У меня также есть ответные заявления.
Вот мой код:
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
22 ответа
В моем случае ошибка произошла только во время тестов 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);
})
);
}
}
В вашем примере кода у вас есть 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';
РЕДАКТИРОВАТЬ: обратите внимание, что, возвращая Observable.throw
в вашем обработчике перехвата вы на самом деле не поймаете ошибку - она все равно появится на консоли.
Если ваша функция ожидает возврата логического значения, просто сделайте это:
- Импортировать:
import { Observable } from 'rxjs/Observable';
- затем
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);
})
}
Вы возвращаете 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
проверить ваше состояние
У меня была эта ошибка, когда в проектах были разные версии RxJS. Внутренние проверки в RxJS не работают, потому что есть несколько разныхSymbol_observable
. В конце концов эта функция выдает один раз вызванный из оператора сглаживания, напримерswitchMap
.
Попробуйте импортировать наблюдаемый символ в некоторой точке входа.
// main index.ts
import 'symbol-observable';
У меня была такая же проблема, вызванная импортом внутренней версии takeUntil вместо операторов Изменить
import { takeUntil } from 'rxjs/internal/operators/takeUntil';
к
import { takeUntil } from 'rxjs/operators';
То же самое и с другими операторами
Я забыл вернуть другой наблюдаемый в pipe(switchMap(
this.dataService.getPerson(personId).pipe(
switchMap(person => {
//this.dataService.getCompany(person.companyId); // return missing
return this.dataService.getCompany(person.companyId);
})
)
Может быть вызвано случайной запятой (,
) в RxJS pipe(...)
Компиляция не поймает эту дополнительную запятую в конце:
pipe(first(), map(result => ({ event: 'completed', result: result}),);
Становится "невидимым" undefined
Оператор, который запутывает всю трубу и приводит к очень запутанному сообщению об ошибке - что в данном случае не имеет ничего общего с моей реальной логикой.
Подсказка для всех, кто сталкивается с этим. Это может произойти, когдаswitchMap
не получает наблюдаемого возвращаемого значения (например, null). Просто добавьте кейс по умолчанию, чтобы он всегда возвращал наблюдаемое.
switchMap((dateRange) => {
if (dateRange === 'Last 24 hours') {
return $observable1;
}
if (dateRange === 'Last 7 Days') {
return $observable2;
}
if (dateRange === 'Last 30 Days') {
return $observable3;
}
// This line will work for default cases
return $observableElse;
})
Я столкнулся с этой проблемой при попытке аутентификации пользователя с помощью веб-токена 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});
}
Я написал это, потому что приехал сюда в поисках той же ошибки, и это может пригодиться кому-то в будущем.
Я получаю ту же ошибку при попытке инициализировать переменную службы из ее конструктора, вызывая удаленный 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 });
}
Что за головная боль:(
Вы также получите следующее сообщение об ошибке, если предоставите undefined или около того для оператора, который ожидает Observable, например. takeUntil.
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
В моем случае в Angular-5 сервисный файл не был импортирован, из которого я получал доступ к методу и подписывал данные. После импорта сервисного файла он работал нормально.
Эта ошибка произошла со мной, когда я использую перехватчик, вы должны сделать это в своем перехватчике
return next.handle(request).map(event => {
if (event instanceof HttpResponse) {
}
return event;
},
catchError((error: HttpErrorResponse) => {
if (error.status === 401 || error.status === 400) {
// some logic
}
Я не уверен, что это кому-то поможет, но в моем случае дальше по цепочке я использовал distinctUntilChanged
и исключение внутри функции проявилось с этим сообщением об ошибке.
Эта ошибка случилась со мной @angular 7
Вы указали недопустимый объект там, где ожидался поток. Вы можете предоставить Observable, Promise, Array или Iterable.
Ошибка на самом деле не требует пояснений, в нем говорится somewhere
в наблюдаемом я передаю недопустимый объект. В моем случае было много вызовов API, но все вызовы не выполнялись из-за неправильной конфигурации сервера. Я пытался использоватьmap
, switchMap
, или другой оператор rxjs, но операторы получают неопределенные объекты.
Так что дважды проверьте вводимые вами операторы rxjs.
Я также столкнулся с той же проблемой, когда вызывал метод внутри switchMap, по-видимому, я обнаружил, что если мы используем метод внутри switchMap, он должен возвращать наблюдаемый.
Я использовал канал для возврата наблюдаемого и отображения для выполнения операций внутри канала для вызова API, который я делал внутри метода, а не подписывался на него.
В моем случае я по ошибке импортировал Action в свой co mbEpics, а не Epic...
Убедитесь, что все функции в CombineEpics являются эпическими функциями
У меня была аналогичная ошибка при использовании RXJS в NESTJS.
Error: TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. +1ms
В моем случае я забыл вернуть Observable в switchMap. Это привело к тому, что в следующем коде оператора или клиента RXJS не было получено Observable.
Как только я вернул Observable в switchMap, ошибка исчезла.
Я получил ту же ошибку с другой проблемой, поэтому я отвечаю на свое решение здесь, чтобы люди, ищущие одно и то же, могли увидеть это.
Я следовал руководству по Supabase + Ionic Auth и хотел добавить проверку электронной почты (с помощью Angular Reactive Forms). Я определил свою группу проверки следующим образом:
credentials = this.fb.nonNullable.group({
email: ['', Validators.required, Validators.email],
password: ['', Validators.required],
})
И когда я добавил Validators.email, я внезапно получил ошибку, я никогда особо не смотрел Validators-lib, но когда я это сделал, я увидел, что вам нужно передать вторые проверки как массив. Так просто меняя['', Validators.required, Validators.email]
к['', [Validators.required, Validators.email]]
исправил проблему!
Рабочее решение:
credentials = this.fb.nonNullable.group({
email: ['', [Validators.required, Validators.email]],
password: ['', Validators.required],
})
У меня точно такое же сообщение об ошибке, когда я проводил свой модульный тест и выдавал наблюдаемое исключение после насмешки над моими услугами.
Я решил, передав точную функцию и формат внутри 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({}));
Приведенный выше код является окей, но когда я пытался проверить условие 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
Что касается ошибки "Вы предоставили недопустимый объект там, где ожидался поток. Вы можете указать Observable, Promise, Array или Iterable".
Это могло произойти, если вы import { Observable } from 'rxjs'
после (ниже) некоторого модуля / функции / чего угодно, который фактически использует его.
Решение: переместите этот импорт выше импорта этого модуля.