简体   繁体   English

RxJS:如何抛出错误然后捕获它?

[英]RxJS : how to throw an error then catch it?

This is not related to a bug I am encountering, but rather a syntax issue.这与我遇到的错误无关,而是与语法问题有关。

The workflow is simple :工作流程很简单:

  • make an HTTP request that returns a boolean发出一个返回布尔值的 HTTP 请求
  • if the boolean is true, then continue如果布尔值为真,则继续
  • if the boolean is false, log a warning, and stop the stream.如果布尔值为 false,则记录警告并停止流。

To manage that, my current code is this :为了管理它,我当前的代码是这样的:

Boilerplate样板

private _getBoolean() { return this.http.get(...); }
private _getData() { return this.http.get(...); }

Current code当前代码

public getData() {
  return this._getBoolean().pipe(
    filter(bool => {
      if(!bool) {
        console.warn('Wrong server answer, stream stopped');
        return false;
      }
      return true;
    }),
    switchMap(bool => this._getData())
  );
}

And I don't know why, but it doesn't feel natural and optimized to me.我不知道为什么,但它对我来说并不自然和优化。

I thought that there would be something that simplifies the syntax, something like this我认为会有一些简化语法的东西,像这样

public getData() {
  return this._getBoolean().pipe(
    throwError(bool => bool ? new Error('Wrong server answer, stream stopped') : null),
    catchError(err => console.warn(err)),
    switchMap(bool => this._getData())
  );
}

Is there something along the lines of that, or do I have the correct syntax ?有没有类似的东西,或者我有正确的语法吗?

Consider the following observable below that emits value 1 to 4. Let's say an error is thrown when the value is 3. That error can be caught in the catchError operator or it can be caught within the subscribe .考虑下面发出值 1 到 4 的以下 observable。假设值是 3 时抛出错误。该错误可以在catchError运算符中捕获,也可以在subscribe捕获。 I believe it depends on the specific use case whether you let the error bubble all the way up to the subscriber or whether it should be handled somewhere upstream of the subscriber.我相信这取决于具体的用例是让错误一直冒到订阅者还是应该在订阅者上游的某个地方处理。

of(1, 2, 3, 4).pipe(
  // Throw error when value is 3
  tap(value => { if(value === 3) throw new Error('Oops!') }),
  catchError(err => {
    console.log('Catch error in operator', err);

    // You can rethrow the same error or a new error
    // return throwError(err);

    // Or you can handle the error and return a new observable
    return of(3)
  })
).subscribe(
  value => console.log(value),
  // If `catchError` returns a new observable, then the error 
  // function here will not be called
  err => console.log('Catch error within subscribe', err),
  () => console.log('Done!')
)

Note that in this example, even if the error is being handled the observable completes and the value 4 is never emitted.请注意,在此示例中,即使正在处理错误,observable 也会完成并且永远不会发出值 4。 If you wish to keep the observable alive when en error is encountered then have a look at this StackOverflow answer .如果您希望在遇到错误时保持 observable 处于活动状态,请查看此 StackOverflow 答案

instead of:代替:

public getData() {
  return this._getBoolean().pipe(
    throwError(bool => bool ? new Error('Wrong server answer, stream stopped') : null),
    catchError(err => console.warn(err)),
    switchMap(bool => this._getData())
  );
}

why not something like:为什么不是这样的:

public getData() {
  return this._getBoolean().pipe(
    tap(result => !result && throwError('Wrong server answer, stream stopped')),
    switchMap(bool => this._getData()),
    catchError(err => console.warn(err))
  );
}

I'm not sure if I get your issue correctly, but you might replace我不确定我是否正确解决了您的问题,但您可以更换

    console.warn('Wrong server answer, stream stopped');
    return false;

With

   Observable.throw('Some error cause')

And then catch it with nearest catch block in your stream, which gives you basically change to: - Stop stream if you re-throw error - Restart it if you return input observable - return completely new observable然后用流中最近的catch块捕获它,这基本上使您更改为: - 如果重新抛出错误,则停止流 - 如果返回输入可观察值,则重新启动它 - 返回全新的可观察值

public getData() {
  return this._getBoolean().pipe(
    filter(bool => {
      if(!bool) {
        console.warn('Wrong server answer, stream stopped');
        //return false;
        Observable.throw('I got false where I expected true')
      }
      return true;
    }),
    switchMap(bool => this._getData())
  );
}

And then:进而:

getData()
.any()
.operator()
.you()
.wish()
.catch(e => {
  /* Here stream will be terminated on thrown error */
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM