2016-11-08 2 views
0

Beim Abrufen von Daten von einer API muss zuerst überprüft werden, ob bereits ein Token gespeichert ist und ob es noch gültig ist. Wenn nicht, muss ich eine neue von der API bekommen und auf die Aktion GET_TOKEN_SUCCESS warten, bevor ich die eigentliche Datenanforderung machen kann.ngrx/effects - Aktionen, die von anderen Aktionen abhängen

Wie gehe ich mit diesem Szenario mit ngrx/effects, ohne die gesamte Logik in einem einzigen Effekt schreiben zu müssen?

Antwort

0

Eine Lösung wäre, die Aktion auszulösen, die das Token erhält, und die Aktion des Effekts erneut auszulösen, wenn ein Token empfangen wird. Man könnte so etwas tun:

@Injectable() 
export class UserEffects { 

    private _tokens: Observable<TokenState>; 

    // Inject the store so that the token can be selected and validated in any 
    // effects. 

    constructor(private _actions_ Actions, private _appStore: Store<AppState>) { 
     this._tokens = this.appStore_.select<TokenState>("token"); 
    } 

    @Effect() 
    createUser = this._actions 
     .ofType("CREATE_USER_REQUEST") 

     // Combine the action with the latest token from the app state. 

     .withLatestFrom(this._tokens, (action, token) => [action, token]) 
     .switchMap(([action, token]) => { 

      if (isValidToken(token)) { 

       // If the token is valid, perform the effect. For example, 
       // this uses a promise-based service: 

       return Observable 
        .fromPromise(this._userService.createUser(token, action.payload)) 
        .map((user) => ({ 
         type: "CREATE_USER_SUCCESS", 
         payload: user 
        }) 
        .catch((error) => Observable.of({ 
         type: "CREATE_USER_ERROR", 
         payload: error 
        })); 

      } else { 

       // If the token is invalid, emit a series of observables. 
       // The first emits the action to get the token and the 
       // second re-emits the original action after the token has 
       // been successfully received. 

       return Observable.concat(
        Observable.of({ type: "GET_TOKEN_REQUEST" }), 
        this._actions.ofType("GET_TOKEN_SUCCESS").first().map(() => action) 
       ); 
      } 
     }); 
} 

du bis DRY könnte eine Funktion (dh die Aktion übergeben wird, das Token und die beobachtbare für das Verhalten der Effekt - dh der beobachtbaren mit dem Service-Aufruf in dem obigen Beispiel) um die Token-Validierung und die beobachtbare Verkettung durchzuführen, da dort nichts drin ist, das effektspezifisch ist.

+0

vielen dank für die antwort! kannst du bitte 'this._actions.ofType (" GET_TOKEN_SUCCESS ") erklären. first(). map (() => action)' ein bisschen mehr? Ich kann diesen Teil nicht zur Arbeit bringen. Es "fängt" nie die Aktion "GET_TOKEN_SUCCESS". Es scheint auch, dass ich 'Observable.concatMap' nicht verwenden kann, nur' observable1.concatMap (() => ...) ', aber ich denke, das sollte keinen Unterschied machen – adamfinstorp

+0

Meine Verwendung von' concatMap' war falsch weil es eher ein Operator als ein beobachtbarer Schöpfer ist. Ich habe die Antwort aktualisiert. Die Absicht war, Observables auszusenden, die in den Aktionsstrom eingeflacht wurden, wobei das zweite Ereignis das ursprüngliche Ereignis erneut emittierte, wenn das Abrufen des Tokens erfolgreich war. Wenn die Antwort immer noch gebrochen ist, werde ich es morgen wiederholen - meine Zeit -, da ich jetzt ziemlich viel Toast bin. – cartant

+0

Verwaltet, um es zu lösen, indem man '.concatMap ((o) => o) ändert;' zu '.concatMap (o => Observable.of (o));'. Ich habe die Antwort bearbeitet, um dies zu reflektieren. Nochmals vielen Dank für Ihre Hilfe! – adamfinstorp