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

Если ваша функция ожидает возврата логического значения, просто сделайте это:

  1. Импортировать:
import { of, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
  1. затем
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