【问题标题】:Property 'do' does not exist on type 'Observable<IProduct[]>''Observable<IProduct[]>' 类型上不存在属性 'do'
【发布时间】:2018-10-16 23:01:55
【问题描述】:

升级到 Angular 6.0 和 Rxjs 到 6.0 后,我收到以下编译错误:

Property 'do' does not exist on type 'Observable'.

代码如下:

import { Observable, of } from 'rxjs';
import 'rxjs/add/operator/do';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import { IProduct } from './product';

@Injectable()
export class ProductService { 
    constructor(
        private product: IProduct)
    {         
    }

    getProduct = () => { 
        return product.products
            // error on next line
            .do(data => console.log('All:' + JSON.stringify(data)))
            .catch(this.handleError);
    }

    private handleError(err: HttpErrorResponse) { 
        console.log(err.message);
        return Observable.throw(err.message);        
    }
}

有什么想法吗?

【问题讨论】:

  • 你能分享一个最小的代码示例来说明这个问题吗?这对于帮助我们调试正在发生的事情大有帮助!
  • import { tap } from "rxjs/operators"; 试试这个return next.handle(clonedReq).pipe(tap((err: any) =&gt; { }));

标签: angular rxjs6


【解决方案1】:

问题不在于角度,而在于 rxjs。 rxjs 引入了 rxjs 版本 6 的重大更改。

要让您的代码在不更改任何代码的情况下再次运行,请安装以下软件包:

npm install rxjs-compat@6 --save

然后您应该能够编译您的项目。 rxjs-compat 是一个临时解决方案,因此您需要更新您的代码库以使用新版本。


新的导入路径

您需要更新的内容:

  1. 更新导入语句

    import { Observable } from "rxjs/Observable";

    import { Observable } from "rxjs";

  2. 更新您的运营商导入来源

    import 'rxjs/add/operator/do'

    import { do } from "rxjs/operators";


重命名运算符

由于与 JavaScript 保留字的名称冲突,一些运算符也已重命名。他们是

  1. do => tap

  2. catch => catchError

  3. switch => switchAll

  4. finally => finalize


无运算符链接

您也不能再链接您的运算符,您需要使用 pipe 运算符,例如

// an operator chain
source
  .map(x => x + x)
  .mergeMap(n => of(n + 1, n + 2)
    .filter(x => x % 1 == 0)
    .scan((acc, x) => acc + x, 0)
  )
  .catch(err => of('error found'))
  .subscribe(printResult);
// must be updated to a pipe flow
source.pipe(
  map(x => x + x),
  mergeMap(n => of(n + 1, n + 2).pipe(
    filter(x => x % 1 == 0),
    scan((acc, x) => acc + x, 0),
  )),
  catchError(err => of('error found')),
).subscribe(printResult);

【讨论】:

  • +1 用于详细说明重命名的运算符。我已经选择了命名空间和管道更改,但错过了名称更改。
  • 更新:import {tap} from 'rxjs/internal/operators';
  • @TjaartvanderWalt 就命名而言没有,但我相信它不再是“可观察”类的属性。相反,它应该作为管道方法的第一个内联方法中的方法调用。来源:stackoverflow.com/questions/50885262/…
  • 所以.do()变成.pipe(tap())
  • 谢谢!我要疯了才能找到这个解决方案:)
【解决方案2】:

我很欣赏 Tjaart van der Walt 关于如何解决 Angular/rxjs7++ 中引入的“重大变化”的回应。但是我在尝试将他的响应应用于我的 Angular 拦截器时仍然遇到了几个问题:

这是更新后的代码(编译失败的部分标记为“OLD”)

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpResponse} from '@angular/common/http';
import {HttpHandler, HttpRequest, HttpErrorResponse} from '@angular/common/http';

/*
  OLD:
  import {Observable} from 'rxjs/Observable';
  import 'rxjs/add/operator/do';
 */
import { Observable } from 'rxjs';
import { of } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';

import { AuthService } from './auth.service';

@Injectable()
export class StockAppInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.authService.authToken) {
      const authReq = req.clone({
        headers: req.headers.set(
          'Authorization',
          this.authService.authToken
        )
      });
      console.log('Making an authorized request');
      req = authReq;
    }
    /*
     * OLD:
     * return next.handle(req)
     *   .do(event => this.handleResponse(req, event),
     *      error => this.handleError(req, error));
     */
    return next.handle(req).pipe(
      tap(
        event => this.handleResponse(req, event),
        error => this.handleError(req, error)
      )
    );
  }


  handleResponse(req: HttpRequest<any>, event) {
    console.log('Handling response for ', req.url, event);
    if (event instanceof HttpResponse) {
      console.log('Request for ', req.url,
          ' Response Status ', event.status,
          ' With body ', event.body);
    }
  }

  handleError(req: HttpRequest<any>, event) {
    console.error('Request for ', req.url,
          ' Response Status ', event.status,
          ' With error ', event.error);
  }
}

所需的更改包括更改import 路径,以及替换pipe()tap()of()

此链接也是 RxJS6 更改的好资源:

https://www.academind.com/learn/javascript/rxjs-6-what-changed/

【讨论】:

    【解决方案3】:

    Rxjs 6 引入了一些重大更改,“do”运算符已被“tap”运算符(来自 'rxjs/internal/operators')取代。

    您可以使用 new 运算符重构您的代码,或者通过添加 rxjs-compat 库以实现向后兼容性 (npm install --save rxjs-compat) 仍然使用旧的“do”语法。

    请注意,在 RxJs 6 之前,您必须导入“do”运算符:

    import 'rxjs/add/operator/do';
    

    更多细节在这里:Angular HTTP GET with TypeScript error http.get(...).map is not a function in [null]

    【讨论】:

    • 已经导入,问题请参考我的代码截图!
    • 如上所述,这对于 rxjs 6.0 或更高版本是正确的。您需要从 rxjs/operators 导入 tap 并更改您的语法。或者导入rxjs-compat@6(“最后的手段”,如果你不能避免更新你的代码)。
    【解决方案4】:

    "do" 运算符已替换为 rxjs 6 中的 "tap" 运算符,这就是为什么 发生此错误“类型上不存在属性'do' '可观察的'"

    要修复此错误,您有两种选择

    解决方案 1:修补您的代码......它可以与 do 运算符一起正常工作

    npm install rxjs-compat@6 --save
    

    解决方案 2:将您的 next.handle 代码替换为以下代码

     return next.handle(req).pipe(
          tap(
            event => this.handleResponse(req, event),
            error => this.handleError(req, error)
          )
        );
    

    【讨论】:

      【解决方案5】:

      只需在您的打字稿文件中使用:

      import 'rxjs/add/operator/do';
      

      就这么简单。 谢谢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-25
        • 1970-01-01
        • 2018-08-11
        • 2018-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多