0

Je suis en train de travailler avec le scénario ci-dessous j'ai deux producteurs A et B. producerB doit exécuter uniquement lorsque producerA est exécuté avec succès et même si producerA lancers francs erreur, gérer l'erreur et arrêter là. J'ai donc essayé quelque chose comme ça.Comment exécuter producerB si et seulement si producerA ne renvoie pas d'erreur?

producerA.flatMapError { 
    // handle error and stop right here 
}.then(producerB).startWithResult { 
    // ... 
} 

On dirait même si producerB exécute producerA lancers francs erreur. S'il vous plaît aidez-moi comment je peux le faire fonctionner avec mon scénario.

+0

Carte/flatMap retourne un tableau. Que voulez-vous dire si cela renvoie une erreur? – user1046037

Répondre

1

La question est de savoir exactement ce que vous voulez dire par "ne pas jeter une erreur".

la séquence d'événements sur un Signal/SignalProducer a une precisely defined semantic

Theres un nombre arbitraire de Value (de 0 - x) Événements, suivie, éventuellement, par un completed, failed ou interrupted événement. Après cela, il n'y a plus d'événements.

En général, on peut dire que la plupart opérateurs ne fonctionnent que sur value événements et se propagent immédiatement failed événements (sans faire fonctionner sur eux). Si vous n'êtes pas sûr d'un opérateur spécifique, jetez un œil à la documentation de cet opérateur qui est très claire sur le comportement des événements d'échec.


donc une façon de comprendre la question est de dire quand producerA se termine correctement (après un nombre arbitraire de value Events), puis lancez producerB et si producerA envoie un failed événement, de ne pas.

Dans ce cas, l'opérateur then correspond exactement à ce dont vous avez besoin. Il commencera producerB dès que producerA se termine, mais pas si producerA échoue!

producerA.then(producerB) 
    .start(Signal.Observer(value: { value in 
    print("Value \(value)") 
    }, failed: {error in 
    print("Error \(error)") 
    })) 

Notez que vous DonT veulent utiliser le flatMapError ici parce que cela (en fonction de la façon dont votre erreur de manipulation dans le bloc semble) convertir failed événements value Les événements qui déclencheraient producerB par la suite.


Une autre façon de comprendre la question est de dire chaque événement sur producerA qui n'est pas une erreur devrait déclencher producerB une fois

Dans ce cas, vous devez utiliser flatMap sur les événements de producerA revenir un producerB pour chaque événement sur producerA.Notez ici, encore une fois, un événement flatMapfailed se propage immédiatement, si un événement failed sur producerA provoquera l'ensemble de la chaîne à l'échec sans exécution de producerB

producerA.flatMap(.concat) { _ in return producerB } 
    .start(Signal.Observer(value: { value in 
    print("Value \(value)") 
    }, failed: {error in 
    print("Error \(error)") 
    })) 
+1

Bonne réponse. Je trouve qu'une bonne façon d'y penser est que 'flatMapError' est essentiellement utilisé pour attraper une erreur. En fait, il [l'habitude d'être appelé catch] (https://github.com/ReactiveCocoa/ReactiveCocoa/commit/e0c266320ba160944eda894210ece7121216f174). Vous ne devriez donc pas l'utiliser si vous voulez réellement que l'erreur termine la chaîne du signal. J'ajouterais que si vous ne voulez pas que toute la chaîne soit terminée en erreur, vous pouvez juste mettre le 'flatMapError' * après *'. (ProducerB) '. – jjoelson

+0

@MeXx je vois un problème ici dans la première approche. Supposons que le premier producteur ne produise pas d'erreur et que le deuxième producteur produise l'erreur, qu'il imprime la valeur et qu'il ne passe jamais au bloc défaillant. – coolly

+0

@coolly, après que 'producerA' envoie sa valeur, est-ce que cela se termine? 'producerB' ne commencera qu'une fois' 'producerA' 'terminé. Vous devriez utiliser la seconde approche avec 'flatMap' si vous voulez que' producerB' démarre quand '' producerA' '' envoie une valeur. – jjoelson