简体   繁体   English

如何很好地向Angular RXJS Observable订户抛出错误

[英]How to nicely throw an error to an Angular RXJS Observable subscriber

For the function below, how can I throw an error from the 'BROKEN' like that can be handled nicely by its subscriber in the same way as the 'WORKS' line of code? 对于下面的函数,我如何从“ BROKEN”引发错误,这样它的订户可以很好地处理该错误,就像使用“ WORKS”代码行一样?

What I'm seeing is that the 'Works' line passes the error neatly this function's subscriber, whereas the BROKEN line just blows up without getting handled by its subscriber. 我所看到的是,“ Works”行巧妙地传递了此函数的订户的错误,而BROKEN行仅被炸毁而没有被其订户处理。 I'm using Angular (version 5.0.3) in an Ionic project, RXJS version 5.5.2, and the HttpClient in @angular/common/http. 我在Ionic项目,RXJS版本5.5.2和@ angular / common / http中的HttpClient中使用Angular(版本5.0.3)。

public makeRequest(requestParameters) {

  return Observable.create(observer => {

    let url = 'http://example.com/service/action?a=b';

    this.http.get(url,{withCredentials: true})
      .subscribe(data => {
        if(data["success"] !== true)
          observer.error("Unexpected result");//BROKEN
        else
          observer.next(data["payload"]);
      },
      err => {
        console.log('error: ' + err);
        observer.error(err);//WORKS
      });
    });
}

Here's an example of a function that calls the one above: 这是一个调用上述函数的示例:

public getStuffFromServer(){
  this.makeRequest({parameters go here}).subscribe(
      data => {
        //do something with the results
      },
      err => {
        //This never gets called from the 'BROKEN' code (but it does from the WORKS code
      }
    );
}

Thanks for your help! 谢谢你的帮助!

So the problem seems to be that in the line: 因此问题似乎出在该行中:

if(data["success"] !== true)
    observer.error("Unexpected result");//BROKEN`

The subscription at this point hasn't experienced an error, in fact the subscription has returned data. 此时的订阅尚未发生错误,实际上该订阅已返回数据。

Try: 尝试:

 observer.next(false);

Or something similar. 或类似的东西。

OK, it looks like I found the answer on this page: https://codingblast.com/rxjs-error-handling/ 好的,好像我在此页面上找到了答案: https : //codingblast.com/rxjs-error-handling/

The key is to use the map and catch functions like so: 关键是使用地图捕获功能,如下所示:

public makeRequest(requestParameters) {

return Observable.create(observer => {
let url = 'http://example.com/service/action?a=b';
this.http.get(url,{withCredentials: true})
  .map(data => {
    if(data["success"] !== true)
      throw new Error("Something meaningful");
    return data["payload"];
   })
  .catch(err => {
    return Rx.Observable.throw(err);
   });
  .subscribe(data => {
      observer.next(data);
  },
  err => {
    console.log('error: ' + err);
    observer.error(err);
  });
});
}

Hopefully this will help somebody. 希望这会对某人有所帮助。 Thank you everyone who answered or gave it some thought! 谢谢所有回答或考虑过的人!

Here is a complete working example how to get internet connection for both, device and browser. 这是一个完整的工作示例,说明如何为设备和浏览器建立互联网连接。 Using Angular 7 and RxJs 6.3.3: 使用Angular 7和RxJs 6.3.3:

The service: 服务:

import {
  Injectable
} from '@angular/core';
import {
  Network
} from '@ionic-native/network';

import {
  Platform
} from 'ionic-angular';

import {
  Observable,
  fromEvent,
  merge,
  of
} from 'rxjs';

import {
  mapTo
} from 'rxjs/operators';

@Injectable()
export class NetworkService {

  private online$: Observable < boolean > = null;

  constructor(private network: Network, private platform: Platform) {
    this.online$ = Observable.create(observer => {
      observer.next(true);
    }).pipe(mapTo(true));
    if (this.platform.is('cordova')) {
      // on Device
      this.online$ = merge(
        this.network.onConnect().pipe(mapTo(true)),
        this.network.onDisconnect().pipe(mapTo(false)));
    } else {
      // on Browser
      this.online$ = merge( of (navigator.onLine),
        fromEvent(window, 'online').pipe(mapTo(true)),
        fromEvent(window, 'offline').pipe(mapTo(false))
      );
    }
  }

  public getNetworkType(): string {
    return this.network.type
  }

  public getNetworkStatus(): Observable < boolean > {
    return this.online$;
  }

}

Wherever you need to check just import the service and use just like this: 无论您需要检查的地方,只需导入服务并按以下方式使用:

...
    this.networkService.getNetworkStatus().subscribe((isConnected: boolean) => {
     console.log('Is it connected? '+isConnected);
    });
...

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

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