类型错误:你提供的对象无效,需要流。你可以提供Observable、Promise、Array或Iterable。

104

我试图从一个服务调用中进行map映射,但是遇到了错误。查看了Angular 2中subscribe未定义?,它说为了订阅我们需要在操作符内部返回。我也有返回语句。

这是我的代码:

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

错误日志:

类型错误:您提供的对象无效,需要流。您可以提供Observable、Promise、Array或Iterable。


2
我收到了一个类似的问题:您提供了'undefined',但预期是流。您可以提供Observable,Promise,Array或Iterable。但这发生在我的服务器正在运行并且我在分支之间切换的时候。我所需要做的就是重新启动服务器,问题便解决了。 - tylerlindell
5
@AakashThakur 你的返回类型是 Observable<boolean>。因此,你所有的返回语句都应该返回一个布尔值的 Observable。用 of() 包装返回语句。例如:1. return of(false) 2. return of(e) - Saddam Pojee
22个回答

50

在我的情况下,错误仅在端到端测试期间发生。它是由于我在AuthenticationInterceptor中使用throwError引起的。

我从错误的来源导入了它,因为我使用了WebStorm的导入功能。我正在使用RxJS 6.2。

错误的:

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

正确:

import { throwError } from 'rxjs';

这里是拦截器的全部代码:

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

如果你正在使用rxjs-compat库过渡到RxJS 6,那么你的项目中可能会同时存在两个版本。 - Stevy
2
我有一个类似的情况,我的拦截器只在 if 语句中执行了 next.handle(request) 调用。因此,在拦截请求后不调用 handle 将导致出现此消息。 - Bancarel Valentin
我曾经遇到过类似的问题,是因为从错误的位置引入了 rxjs 中的 interval。这个答案非常有帮助,谢谢! - Alexander Nied
在我的情况下,我只有 return 而没有 return throwError(error) 。谢谢您的答案。 - Utkarsh
我无法强调这个答案有多么重要!解决了我连续两天关注的问题...谢谢! - rub
我在拦截器中明确发送了空头信息。正是因为它在拦截器中,才真正起到了帮助作用。 - undefined

21
在您的示例代码中,您的map操作符接收了两个回调函数,但它只应该接收一个。您可以将错误处理代码移到catch回调函数中。

在您的示例代码中,您的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);
                       })
   }

你还需要导入catchthrow 运算符。

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

编辑:请注意,在catch处理程序中返回Observable.throw,你实际上不会捕获错误 - 它仍会出现在控制台上。

注:如果在catch处理程序中返回Observable.throw,那么实际上不会捕获错误,它仍然会在控制台上显示。


但是现在我得到了这个错误:Error: Uncaught (in promise): [object ProgressEvent] - Aakash Thakur
你可以尝试将 Observable.throw 行更改为 Observable.of(并包含导入)。这将导致你的可观察对象发出错误,但不会将其视为失败。(基本上我们有点/但并没有完全吞下错误)。请查看是否从控制台中删除了该错误。如果是,则说明 getData() 方法失败了。 - snorkpete

18

如果你的函数希望返回一个布尔值,只需执行以下操作:

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

10

你返回了一个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来检查你的条件。


我必须返回一个Observable<boolean>,因为我必须在其他某些函数中使用它。 - Aakash Thakur
你的getData()函数返回什么? - Aravind
getData() 返回 [object Object]{id: "1234", isAdmin: false, userName: "Lama", newid: Array[1]} - Aakash Thakur
对不起,兄弟。我不是。 - Aakash Thakur
我无法复制或向您展示我的屏幕,因为这不是一个家庭项目,而是一项机密任务,这只是其中出现问题的一部分。 - Aakash Thakur
好的。你能否更新你的代码流程以进行发布?完整的流程? - Aravind

7

在不同的RxJS版本之间出现问题时,我曾遇到过这个错误。RxJS内部检查失败,因为存在多个Symbol_observable。最终,像switchMap这样的扁平化操作符调用此函数时会发生异常。

尝试在某个入口点导入symbol-observable。

// main index.ts
import 'symbol-observable';

6
我曾因导入 'takeUntil' 的内部版本而遇到了相同的问题,而不是运算符。 更改为:

我曾经遇到了同样的问题,由于导入了'takeUntil'的内部版本而不是运算符。

import { takeUntil } from 'rxjs/internal/operators/takeUntil';

to

import { takeUntil } from 'rxjs/operators';

这也会发生在其他运算符中。

5

我忘记在pipe(switchMap(中返回另一个可观察对象。

this.dataService.getPerson(personId).pipe(
  switchMap(person => {
     //this.dataService.getCompany(person.companyId); // return missing
     return this.dataService.getCompany(person.companyId);
  })
)

我的单元测试中,我没有正确地模拟switchMap返回的可观察对象,结果相同。 - Kevin Beal

4

一个放错位置的逗号(,)可能会触发 RxJS pipe(...) 函数

编译器无法捕获到在结尾多余的逗号:

pipe(first(), map(result => ({ event: 'completed', result: result}),);

它变成了一个“无形”的 undefined 运算符,这会搞砸整个管道,并导致非常令人困惑的错误信息 - 而这种情况与我的实际逻辑无关。


3

对于遇到此问题的人,有一个提示。当一个 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;
        })

这是我的情况,我正在测试一个函数,但是我不需要 switchMap 返回的可观察对象的返回值,所以我没有模拟它,不过这对我有帮助,谢谢。 - KoboldMines

2

我在尝试使用JSON Web Token对用户进行身份验证时遇到了问题。在我的情况下,这与身份验证拦截器有关。

向服务器发送身份验证请求时不需要提供令牌,因为令牌尚不存在。

请检查您的拦截器是否包括以下内容:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接