错误后不要关闭Observable

时间:2017-03-15 19:09:45

标签: angular typescript rxjs observable

我知道这个问题看起来很简单,但网上关于Observables和错误处理的资源并不是那么好(或者我在搜索时可能不好)。

我有一个http请求,它返回响应 Observable ,这些响应可以包含数据或错误消息。如果它包含我要提取的数据并解析它,如果它包含错误消息我想跳过所有其他运算符(关于解析)并在订阅者中执行错误函数。

我可以做所有这些抛出错误的事情:

http.get(...).
...
.do(res=>{
  if(res.error) throw new Error(res.error.message);
  return res;
})

并且它有效,它会跳过所有操作符并执行错误功能。问题是,在出现错误后, Subscriber 停止并且不再接受数据。

如果我在错误后分析了订阅者,我注意到属性关闭 isStopped 都设置为 true 。我想防止这种情况,我想在错误发生后保持Observable活动。我该怎么办?

谢谢

2 个答案:

答案 0 :(得分:3)

你所要求的实际上违反了Observable的合同。 Observable被定义为0或更多值的生成器,如果生成器完成生成值,它将在其观察者上调用complete处理程序,如果有错误,它将调用error

但是一旦它调用completeerror,它的合同就是它永远不再会在其观察者身上调用next

有很多方法可以解决这个问题 - 通过正确地组合你的observable,你可以用一个新的observable恢复你的流。但没有额外的背景,很难引导你进一步。基本思想是在您的可观察链中使用.catch运算符来创建一个新的可观察错误,但同样需要额外的上下文来提供示例。

修改

正如@cartant有帮助地添加了see the observable contract

答案 1 :(得分:2)

如前面的答案中所述,这是标准行为,由Rxjs观察者的合同保证。如果你想逃避合同,你可以materialize你的来源,在这种情况下,你不会处理通过你的observable流传输的消息,你将处理元消息(称为通知,你有三种类型)期待,nexterrorcomplete)。元消息没有合同,这会给您带来创建错误的负担,并手动完成消息,或者使用dematerialize返回正常行为。

一般来说,可观察对数据流非常有用,而控制流通常很艰巨(跳跃,循环,条件分支等)。

请在此处查看Notification文档:http://reactivex.io/rxjs/class/es6/Notification.js~Notification.html

请在此处查看materialize文档:http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-materialize

因此,如果您想在不停止源可观察的情况下处理错误,您可以执行以下操作:

function process(source, success, error) {
  return source.materialize()
    .map(function(notification){
      const value = notification.value; // that is the actual message data
      if (notification.kind === 'N') {
        // that is a next message, we keep it a next message
        return Notification.createNext(success(value));
      }
      if (notification.kind === 'E') {
        // that is a error message, we turned into a next message
        return Notification.createNext(error(value));
      }
      if (notification.kind === 'C') {
        // that is a completed message, we keep it a completed message
        return Notification.createComplete();
      }
    })
   .dematerialize()
}

然后,您可以将此函数与source observable一起使用,并将成功和错误函数传递给它,该函数处理流值。如您所见,此处的技术是将错误消息转换为正常消息,然后恢复正常。

这是从头脑中完成的,所以未经测试,所以如果这对你有帮助,请保持更新。我使用类似的技术多次使用Rxjs v4,我相信它应该直接转换为Rxjs v5。