首页 文章

Angular - RxJS运算符.first()在从Http升级到HttpClient后抛出类型错误

提问于
浏览
1

我最近升级了我的角度应用程序以使用HttpClient而不是Http . 在处理了header和params的一些修复程序之后,我的大多数代码都工作了,但是一个特定的请求暗示了我的奇怪行为 .

请求有点特殊,因为它是一个轮询请求,当它从服务器获得有效负载时会发出失败(它将返回204响应,直到它有东西要传递) .

我正在使用一个Observable间隔在特定的时间 Span 内每秒轮询一次 endpoints ,当我得到一个有效负载时,我使用.first()运算符来处理数据 . 当我使用旧的Http服务时,这很好用 . 以下是它的外观:

return Observable.interval(this.pollInterval)
  .mergeMap(() => this.http.get(this.apiUrl + '/poll'))
  .first(data => data) // This is where the error occurs in HttpClient
  .map(result => result)
  .timeout(20000)
  .catch(this.errorHandler);

当我使用不推荐使用的Http服务时,observable可以正常工作,但是当我使用HttpClient服务时,我收到以下错误:

error TS2345: Argument of type '(data: Object) => Object' is not assignable to parameter of type '(value: Object, index: number, source: Observable<Object>) => boolean'. Type 'Object' is not assignable to type 'boolean'.

现在这里有点奇怪,我决定尝试通过在.first()运算符之前添加.do(console.log)来调试可观察流,如下所示:

return Observable.interval(this.pollInterval)
  .mergeMap(() => this.http.get(this.apiUrl + '/poll'))
  .do(console.log)
  .first(data => data)
  .map(result => result)
  .timeout(20000)
  .catch(this.errorHandler);

这样做似乎解决了问题,没有更多的类型分配错误,并且想要的功能像以前一样工作 . 我已经使用了一个我在.do()操作符中调用的虚函数,但是我不满意必须这样做才能解决问题,所以我想弄清楚为什么会出现这种行为以及是什么.do()运算符可以解决问题 .

期待听到您对此问题的意见 .

Solution 我按照第一个答案的建议使用!!在.first()返回中将数据类型转换为boolean,这消除了类型错误,并删除了使用问题中描述的.do()操作的需要 .

1 回答

  • 1

    如果 do() 解决了问题,它实际上似乎是 do() 与RxJS <5.5的打字中的错误 . 该运算符仅用于副作用,不应以任何方式改变链 . 所以检查你RxJS版本,也许这是问题https://github.com/ReactiveX/RxJS/commit/9a40297 .

    无论如何 first() 的回调需要以下类型(http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-first):

    function(value: T, index: number, source: Observable<T>): boolean
    

    我认为错误告诉你's wrong. You'正在使用 first(data => data) 所以你没有返回 boolean 而是 Object .

    如果我理解你想要做什么,你需要根据它是否存在将对象变为 truefalse .

    .first(data => !!data)
    

    ......或者可能不是蹩脚的解决方案:

    .first(Boolean)
    

    另一个问题是你是否需要使用 first . 这意味着如果源Observable完成并且没有匹配的项目或者它已经完成并且有多个匹配的项目并且我认为在您的情况下没有这些chan发生则发出错误 . 所以也许使用 filter(Boolean) 会更有意义 .

相关问题