【问题标题】:How to throw an observable error manually?如何手动抛出可观察到的错误?
【发布时间】:2017-03-23 13:22:23
【问题描述】:

我正在开发一个 Angular 应用程序,在该应用程序中我通过 HTTP 进行休息调用,如下所示:

login(email, password) {
    let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    let options = new RequestOptions({ headers: headers });
    let body = `identity=${email}&password=${password}`;
    return this.http.post(`${this._configService.getBaseUrl()}/login`, body, options)
    .map((res: any) => {
        let response: any = JSON.parse(res._body);
        if (response.success == 0) {
          Observable.throw(response);  // not working
        } else if (response.success == 1) {
          console.log('success');
          localStorage.setItem('auth_token', 'authenticated');
          this.loggedIn = true;
          return response;
        }
    });
}

基本上我希望我的组件在订阅调用中得到响应和错误,即

this._authenticateService.login(this.loginObj['identity'],this.loginObj['password']).subscribe(
  (success)=>{      
    this.credentialsError=null;  
    this.loginObj={};  
    this._router.navigate(['dashboard']);    
  },
  (error)=>{
    console.log(error);        
    this.credentialsError=error;     
  }
);

但我的 API 总是返回成功,因为它是这样定义的。

如果是response.success == 0,我如何抛出错误消息,以便在订阅回调的错误参数中访问它?

【问题讨论】:

  • 你得到的状态码是什么,我的意思是它可以是0?
  • @MrJSingh 设计 API 的人只返回成功为 0 或 1 来验证响应。所以我的操作是成功的,它会返回成功 =1 或者它会返回成功 = 0 .now如果成功为 0,我想抛出错误。这可能吗?
  • 让我试试我的应用,技术上应该是可以的。
  • 试试这个 return Observable.throw(response);
  • 您可以尝试这样做:这是一个类似的案例stackoverflow.com/a/55286461/8342681

标签: javascript angular typescript rxjs


【解决方案1】:

rxjs 7

throwError(() => new Error(response))

更多信息 https://rxjs.dev/deprecations/breaking-changes#throwerror

【讨论】:

    【解决方案2】:

    这是官方示例(发出数字 7,然后发出错误“哎呀!”):

    import { throwError, concat, of } from 'rxjs';
    
    const result = concat(of(7), throwError(new Error('oops!')));
    result.subscribe(x => console.log(x), e => console.error(e));
    

    来自: https://rxjs-dev.firebaseapp.com/api/index/function/throwError

    【讨论】:

      【解决方案3】:

      rxjs 5

      要么

      throw response;
      

      throw Observable.throw(response);
      

      【讨论】:

      • 第二个是:throw Observable.throw(response)
      • +1 表示简单的throw response。其他一切,例如返回一个 ErrorObservable 或在 map 中抛出一个 ErrorObservable 并不理想,因为您最终会得到一个嵌套的 Observable。
      • 第二个被弃用了吗?
      • @Farhad 是的,它已被弃用。正确答案见stackoverflow.com/a/40512534/5493813
      【解决方案4】:
      if (response.success == 0) {
         throw Observable.throw(response);  
       } 
      

      编辑 rxjs 6

      if (response.success == 0) {
         throw throwError(response);  
       } 
      

      【讨论】:

      • 即使不使用它,我也会在成功回调中得到它
      • 我不明白,即使不使用它是什么意思?你能给我解释一下吗?我按照您的情况对其进行了测试,并且仅当成功为 0 时 Observable 才会抛出错误。
      • 我的意思是,如果我的响应返回任何内容,无论是错误还是成功,它都会将其返回到成功回调中。我希望在错误回调中抛出错误..
      • 这个答案已经过时了。
      • 这将在错误回调中返回一个 Observable,这不是好的代码设计。而是抛出你自己的错误对象throw { message: 'Bad response', value: response}
      【解决方案5】:

      通常,当您抛出错误时,您会在问题发生的确切时刻这样做,并且您想立即提出它,但情况可能并非总是如此。

      例如,有timeoutWith() 运算符,这可能是您需要这样做的最可能原因之一。

      results$ = server.getResults().pipe(timeoutWith(10000, ....) )
      

      这需要一个“错误工厂”,它是一个函数。

       errorFactory = () => 'Your error occurred at exactly ' + new Date()
      

      例如。

      results$ = server.searchCustomers(searchCriteria).pipe(timeoutWith(10000, 
                    () => 'Sorry took too long for search ' + JSON.stringify(searchCriteria)) )
      

      请注意,当使用timeoutWith 时,您将永远不会得到实际的服务器响应 - 因此,如果服务器给出特定错误,您将永远不会看到它。上面的这个例子在调试中非常有用,但是如果你使用上面的例子,请确保不要向最终用户显示错误。

      错误工厂很有用,因为它在实际错误发生之前不会评估代码。因此,您可以将“昂贵”或调试操作放入其中,当最终需要错误时执行。

      如果您需要使用“工厂”在超时以外的地方创建错误,您可以使用以下内容。

       EMPTY.pipe(throwIfEmpty(errorFactory)) 
      

      【讨论】:

        【解决方案6】:

        使用 rxjs 6

        import { throwError } from 'rxjs';
        throwError('hello');
        

        【讨论】:

        • 请解释一下为什么它比语言的原生部分(即throw 关键字)更好?
        • @Endrju 完全不同。 return throwError 将返回 observable,然后您可以使用 catchError 或内部订阅处理。如果你抛出 new Error('') 这会冒泡并且不会在 observables 中处理......
        • 只是打电话给throwError 对我不起作用。
        【解决方案7】:

        我的大部分问题都与导入有关,所以这是对我有用的代码...

        import {_throw} from 'rxjs/observable/throw';
        login(email, password) {
        ...
            return this.http.post(`${this._configService.getBaseUrl()}/login`, body, options)
            .map((res: any) => {
        ...
                if (response.success == 0) {
                   _throw(response);  
                } else if (response.success == 1) {
        ...
                }
            });
        }
        

        如果您遇到诸如...之类的错误,这将是解决方案

        错误类型错误: WEBPACK_IMPORTED_MODULE_2_rxjs_Observable.Observable.throw 不是函数

        【讨论】:

          【解决方案8】:

          rxjs 6

          import { throwError } from 'rxjs';
          
          if (response.success == 0) {
            return throwError(response);  
          }
          

          rxjs 5

          import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
          
          if (response.success == 0) {
            return new ErrorObservable(response);  
          }
          

          ErrorObservable 返回的内容由您决定

          【讨论】:

          • 接受的答案解决方案在 rxjs6 中已弃用。谢谢你,你的作品:)
          • 这是在预期返回像 switchMapmergeMap 这样的 Observable 的运算符中使用时要走的路。在map 中使用时,您最终会得到一个嵌套的 Observable(您将在 Observable 的成功回调中获得一个 Observable),这可能不是您想要的。
          【解决方案9】:

          使用 catch 操作符

          this.calcSub = this.http.post(this.constants.userUrl + "UpdateCalculation", body, { headers: headers })
             .map((response: Response) => {
                var result = <DataResponseObject>response.json();
                   return result;
             })
             .catch(this.handleError)
             .subscribe(
                dro => this.dro = dro,
                () => this.completeAddCalculation()
             );
          

          并像这样处理错误:

          private handleError(error: Response) {
              console.error(error); // log to console instead
              return Observable.throw(error.json().error || 'Server Error');
          }
          

          【讨论】:

          • 我的 api 从不调用 catch 块。这就是我遇到的问题。在我的回复中,我想检查某些条件,然后抛出错误或调用 catch 块。
          • 我在私有 handleError(error: Response) WEBPACK_IMPORTED_MODULE_2_rxjs_Observable中遇到了这个错误。a.throw 不是 CatchSubscriber.selector 的函数
          • @NamLe 你必须导入 throw 才能使用它。 import 'rxjs/add/observable/throw';
          猜你喜欢
          • 2020-01-08
          • 2021-03-25
          • 2014-02-24
          • 2018-10-15
          • 1970-01-01
          • 2019-02-04
          • 2020-01-03
          • 1970-01-01
          相关资源
          最近更新 更多