【问题标题】:RxJS : how to throw an error then catch it?RxJS:如何抛出错误然后捕获它?
【发布时间】:2019-04-13 00:02:03
【问题描述】:

这与我遇到的错误无关,而是语法问题。

工作流程很简单:

  • 发出返回布尔值的 HTTP 请求
  • 如果布尔值为真,则继续
  • 如果布尔值为假,则记录警告并停止流。

为了管理它,我当前的代码是这样的:

样板文件

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

当前代码

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())
  );
}

我不知道为什么,但它对我来说并不自然和优化。

我认为会有一些东西可以简化语法,就像这样

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())
  );
}

有没有类似的东西,或者我有正确的语法?

【问题讨论】:

    标签: angular typescript rxjs rxjs-pipeable-operators


    【解决方案1】:

    我不确定我是否正确地解决了您的问题,但您可以替换

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

    有

       Observable.throw('Some error cause')
    

    然后在您的流中用最近的catch 块捕获它,这使您基本上可以更改为: - 如果您重新抛出错误,则停止流 - 如果您返回可观察的输入,请重新启动它 - 返回全新的 observable

    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())
      );
    }
    

    然后:

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

    【讨论】:

    • 在 rxjs 6 中,可观察原型的使用难道不是一种不好的做法吗?
    • 在 RxJS 6 中是的,确实如此。不幸的是,我目前的经验是基于 5.5 :( 你应该通过使用管道包装除 catch 之外的所有运算符来获得相同的结果
    • 同样的事情,我认为 catch 是一个不好的做法,你应该使用订阅的第二个回调......因此我的问题,就像你一样,我的经验基于
    • @trichetriche 你能否分享一些参考,说在可观察链中捕获是一种不好的做法? subscribe 中的第二个回调有不同的目的:它将处理订阅中的错误,但那个 observable 在那个时间点已经消失了。所以它的用法不同。
    • 顺便说一句,Observable.throw 变成了throwError() 操作员
    【解决方案2】:

    考虑下面的 observable,它发出值 1 到 4。假设当值为 3 时抛出错误。该错误可以在 catchError 运算符中捕获,也可以在 subscribe 中捕获。我相信这取决于具体的用例,是让错误一直冒泡到订阅者,还是应该在订阅者上游的某个地方处理。

    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!')
    )
    

    请注意,在此示例中,即使正在处理错误,observable 也会完成并且永远不会发出值 4。如果您希望在遇到 en 错误时保持 observable 活动,请查看this StackOverflow answer。

    【讨论】:

    • 我也试过这个解决方案,因为它是我在网上找到的第一个。这段代码的问题是抛出的错误是 Javascript 错误,并在控制台中显示为实际的 JS 错误。我可能听起来很挑剔,但我的代码没有 JS 错误,只是从服务器返回的布尔值设置为 false ......所以这个解决方案不适合我(但我会赞成它,因为它可能会帮助其他人)
    • 有什么东西阻止你使用tap(bool => { if(bool) throw new Error('Wrong server answer') }),即当服务器给你错误时你创建了一个JS错误?只要你抓住它,它就不应该显示在控制台中。
    • 这就是诀窍,你实际上并没有抓住它,试一试,你会看到它在你的控制台中弹出。它困扰着我(不是我,我的 N+1),因为服务器响应是 200,而不是 400 或 500,所以这不是错误(我简化了示例,我当然不请求简单的布尔值服务器)
    【解决方案3】:

    代替:

    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())
      );
    }
    

    为什么不这样:

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

    【讨论】:

    • 如果您不返回任何内容,那会捕获错误吗? (我正在打电话,我现在无法测试)
    • 什么都不返回是什么意思?从哪里?并且,在这种情况下会出现什么错误?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2018-01-21
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多