web-dev-qa-db-fra.com

RxJs intercepte l'erreur et continue

J'ai une liste d'éléments à analyser, mais l'analyse de l'un d'entre eux peut échouer.

Quel est le "Rx-Way" pour attraper l'erreur mais continuer à exécuter la séquence

Exemple de code:

var observable = Rx.Observable.from([0,1,2,3,4,5])
.map(
  function(value){
      if(value == 3){
        throw new Error("Value cannot be 3");
      }
    return value;
  });

observable.subscribe(
  function(value){
  console.log("onNext " + value);
  },
  function(error){
    console.log("Error: " + error.message);
  },
  function(){
    console.log("Completed!");
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>

Ce que je veux faire d'une manière non-Rx-Way:

var items = [0,1,2,3,4,5];

for (var item in items){
  try{
    if(item == 3){
      throw new Error("Value cannot be 3");
    }
    console.log(item);
  }catch(error){
     console.log("Error: " + error.message);
  }
}

Merci d'avance

37
Cheborra

Je suggérerais que vous utilisiez plutôt flatMap (maintenant mergeMap dans la version 5 de rxjs), ce qui vous permettra de réduire les erreurs si vous ne vous en souciez pas. Effectivement, vous allez créer un observable interne qui peut être avalé en cas d'erreur. L'avantage de cette approche est que vous pouvez chaîner des opérateurs. Si une erreur se produit n'importe où dans le pipeline, elle sera automatiquement transmise au bloc d'interception.

var observable = Rx.Observable.from([0, 1, 2, 3, 4, 5])
  .flatMap((value) =>          
    Rx.Observable.if(() => value != 3,
      Rx.Observable.just(value),
      Rx.Observable.throw(new Error("Value cannot be 3")))
    //This will get skipped if upstream throws an error
    .map(v => v * 2)
    .catch((err) => {
      console.log("Caught Error, continuing")
      //Return an empty Observable which gets collapsed in the output
      return Rx.Observable.empty();
    })
  );

observable.subscribe(
  (value) => console.log("onNext " + value), (error) => console.log("Error: " + error.message), () => console.log("Completed!")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
34
paulpdaniels

Vous devez passer à un nouveau flux jetable. Si une erreur se produit, il sera éliminé en toute sécurité et conservez le flux d'origine:

Rx.Observable.from([0,1,2,3,4,5])
    .switchMap(value => {

        // This is the disposable stream!
        // Errors can safely occur in here without killing the original stream

        return Rx.Observable.of(value)
            .map(value => {
                if (value === 3) {
                    throw new Error('Value cannot be 3');
                }
                return value;
            })
            .catch(error => {
                // You can do some fancy stuff here with errors if you like
                // Below we are just returning the error object to the outer stream
                return Rx.Observable.of(error);
            });

    })
    .map(value => {
        if (value instanceof Error) {
            // Maybe do some error handling here
            return `Error: ${value.message}`;
        }
        return value;
    })
    .subscribe(
      (x => console.log('Success', x)),
      (x => console.log('Error', x)),
      (() => console.log('Complete'))
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>

Plus d'informations sur cette technique dans cet article de blog: La quête de boulettes géantes: continuez les flux RxJS en cas d'erreur

25
iamturns

Vous pouvez réellement utiliser try/catch à l'intérieur de votre fonction map pour gérer l'erreur. Voici l'extrait de code

var source = Rx.Observable.from([0, 1, 2, 3, 4, 5])
    .map(
        function(value) {
            try {
                if (value === 3) {
                    throw new Error("Value cannot be 3");
                }
                return value;

            } catch (error) {
                console.log('I caught an error');
                return undefined;
            }
        })
    .filter(function(x) {
        return x !== undefined; });


source.subscribe(
    function(value) {
        console.log("onNext " + value);
    },
    function(error) {
        console.log("Error: " + error.message);
    },
    function() {
        console.log("Completed!");
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
0
Toan Nguyen