【问题标题】:Type 'void' is not assignable to type 'ObservableInput<{}>'类型 'void' 不可分配给类型 'ObservableInput<{}>'
【发布时间】:2017-03-30 10:37:10
【问题描述】:

在我迁移到 TS 2.2.2 后开始出现此错误,所以我假设是问题所在...代码没有停止工作,但现在我收到了该错误,我尝试了一些操作,例如返回一个空的可观察对象,捕获重新抛出的异常并返回一个对象,似乎没有任何效果。为什么现在会发生这种情况?难道它不应该理解我正在重新抛出异常并且不期望返回吗?我是否误读了错误?

这是完整的错误描述:

这是完整的代码:

return request
    .map((res: Response) => res.json())
    .catch((error: any) => {
        // todo: log?

        if (error.status == 500) {
            this.alertService.showError(error.statusText);
        } else if (error.status == 588) {
            this.alertService.showAlert(error.statusText);
        }

        Observable.throw(error.statusText);
    });

我尝试返回 Observable,但我的包装器方法期望返回类型为 T,这是我的反序列化请求 (map(...)) 的返回。如果我确实返回 throw 这是我得到的错误:

[ts] 类型“Observable”不可分配给类型“T”

我正在使用:

  • Angular4
  • 打字稿 2.2.2

【问题讨论】:

    标签: typescript angular4


    【解决方案1】:

    你必须返回 Observable

     return request
        .map((res: Response) => res.json())
        .catch((error: any) => {
            // todo: log?
    
            if (error.status == 500) {
                this.alertService.showError(error.statusText);
            } else if (error.status == 588) {
                this.alertService.showAlert(error.statusText);
            }
    
            return Observable.throw(error.statusText);
        });
    

    【讨论】:

    • 嘿,谢谢你的回答,我以前试过。它不起作用,因为我的包装器方法需要返回 T 类型。请检查我更新的问题。对不起,我忘了补充。再次感谢。
    • Bougarfaoui,我将其标记为答案,因为我现在能够找出问题所在:) 在您回答之后,我决定更仔细地查看代码,我确实应该返回它(尽管这个概念对我来说仍然有点奇怪,因为它正在被重新抛出),但问题是我的包装方法的预期回报。一旦我将其更改为期望 Observable 它就起作用了。谢谢。
    • 请注意,在 RxJS 更新后,命令现在是 Observable.throwError(而不仅仅是 .throw)。
    • 抛出错误(响应);或抛出 Error(err);
    • 我收到了Property 'throwError' does not exist on type 'typeof Observable'. ts(2339) (RxJS 7.4)。与throw 相同。
    【解决方案2】:

    有时当你调用 catch 而不使用如下箭头函数时

    getUserList() {
        return this.http.get(this.constURL + '/api/url/here', this.headerOptions)
        .catch(this.handleError);
    }
    
    handleError(error: Response) {
        if (error.status == 500) {      
          this.router.navigate(['/login']);
        } else {
          return Observable.throw(error);
        }
    }
    

    然后它给出了错误

    ERROR TypeError: Cannot read property 'navigate' of undefined not getting this

    因为在 handleError 函数中这个对象是不可访问的..如果你控制台 this.router 那么你会得到 undefined.. 所以这个对象不工作并且没有得到路由器所有可用的方法

    所以你必须在这里使用箭头功能,如下所示

    getUserList() {
        return this.http.get(this.constURL + '/api/url/here', this.headerOptions)
        .catch(error => { 
          return this.handleError(error);
        });
    }
    
    handleError(error: Response) {
        if (error.status == 500) {      
          this.router.navigate(['/login']);
        } else {
          return Observable.throw(error);
        }
    }
    

    另外,如果你没有提到 handlerError 函数的返回,那么它会再次抛出错误

    '(error: any) => void' 类型的参数不能分配给类型参数

    所以有必要为 handlerError 函数键入 return。

    详细检查here。他很好地解释了代码,包含所有可能的错误和解决方案..为我工作

    【讨论】:

    • 您真的不应该从与 OP 的答案无关的其他应用程序中粘贴长的生产代码 sn-p。这让阅读答案的人感到困惑,对 OP 来说有点无益。
    • 嗨 tshm001,我想我试图解释 OP 问题所需的代码。它不是生产代码,而是通过添加一些实际的服务名称使其可读..如果需要更改,请告诉我,我会做..谢谢
    【解决方案3】:

    这是 RXJS 6 的角度 6 的答案。 在您的请求函数中,它看起来与此类似。请注意,catch 已替换为 catchError 并且 Observable.throw 现在是 throwError。同样在 RXJS 6 中,我们使用管道将我们希望执行的一系列函数连接在一起,而不是之前的点链接。

    //In your service
    
    getData(url: string): Observable<any> {
        let options = this.getHTTPOptions();
        return this.http.get<any>(url, options).pipe(
              catchError( (err: any, caught: Observable<any>) => { return 
            throwError(this.generalErrorHandler(err, caught)) } ) );
    }
    

    然后你可以有一个错误处理程序。关键是在上面的catchError函数中都指定关键字return,并在处理程序中返回错误。 箭头 (=&gt;) 允许您将调用函数的上下文传递给错误处理程序,这意味着您可以做一些很酷的事情,例如 this.router.navigate(['someroute']);(如果您的服务中导入了路由器)

    //In your service
    
      generalErrorHandler(error: any, caught: Observable<any>): Observable<any> {
        console.log('error caught: ', error);
        if( error.error.status == "INVALID_TOKEN" || error.error.status == "MAX_TOKEN_ISSUE_REACHED"){
          console.log('token has expired');
          this.logout();
          return error;
        }
        return error;
      }
    

    一些关键的进口让这个工作:

    //Imports for the service
    
    import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
    import { Http, Response } from '@angular/http';
    import { catchError, map } from 'rxjs/operators';
    import { Observable, throwError, of} from 'rxjs';
    

    最后订阅请求以获取您的数据:

    //In your component, don't forget to import your service
    
    let response$ = this.someService.getData('url here');
    response$.subscribe( 
        data => { console.log('do stuff to data here', data); },
        err => { console.log("couldn't get data, maybe show error to user"); },
        () => { console.log('function that is called upon finish'); }
    );
    

    【讨论】:

      【解决方案4】:
       return Observable.throw(error);
      

      可观察的。不推荐使用 throw 在拦截器中使用 throwError 运算符

      intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
         return next.handle(request).pipe(
          catchError(err => {
            if (err.status === 401) {
             // remove Bearer token and redirect to login page
              this.router.navigate(['/auth/login']);
            }
            return throwError( err );
          }));
      }
      

      【讨论】:

      • 我收到了Property 'throwError' does not exist on type 'typeof Observable'. ts(2339) (RxJS 7.4)
      猜你喜欢
      • 2019-05-06
      • 2020-10-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 2019-01-04
      • 1970-01-01
      • 2021-12-05
      相关资源
      最近更新 更多