2016-06-04 3 views
32

nugrx/store 1.5를 썽크 미들웨어와 함께 사용하는 응용 프로그램에서 작업하고 있고 ngrx/store 2.0 및 ngrx/effects로 이동하려고합니다. 여러 가지 관련 작업 및/또는 효과를 처리하는 방법과 관련하여 몇 가지 질문이 있습니다.ngrx/effects를 사용하여 여러 관련 작업/효과/작업을 수행하는 방법

나는 썽크와 이펙트의 "사고 방식"이 다르다는 것과 다른 점을 생각하면서 머리를 쓰려고한다는 것을 알고 있습니다. 내가 사용할 수있는 예제 애플 리케이션을 통해 보았고, 내가 시도하고있는 것에 맞을 것으로 보이지 않는 것을 찾지 못했고, 아마도 나는 여전히 그것을 완전히 틀리게 접근하고있다. 을 감안할 때

@Effect login$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN) 
    .map(toPayload) 
    .switchMap(payload => 
     this.loginService.login(payload.user, payload.password) 
      .map(result => this.actions.loginSuccess(value)) 
      .catch((error) => Observable.of(this.loginError(error))) 
)); 

초기 부작용은, 무엇은 "올바른 될 것이라고 : 여기에 시나리오 1

는 로그인을 위해 서버로 요청을 처리 할 수있는 부작용입니다 로그인 성공시 "집"화면으로 탐색을 시작하는 "또는"제안 된 "방법? 이것은 일련의 행동이나 조작을 단순히 유발하는 것으로 일반화 될 수도 있습니다.

몇 가지 옵션을 나는 생각했다 :

(A) 탐색을 트리거 후속 조치를 발사 로그인 성공에 의해 트리거 또 다른 효과를?

@Effect navigateHome$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN_SUCCEEDED) 
    .mapTo(this.actions.navigateHome()); 

(b) 로그인 성공에 의해 유발 된 또 다른 효과는 단순히 탐색 작업을 수행하는 것입니까?

@Effect navigateHome$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN_SUCCEEDED) 
    .do(this.navigateHome()) 
    .filter(() => false); 

(c) 초기 로그인 효과에 의해 방출 된 액션을 추가로 연결 하시겠습니까? (샘플은 분명히 정확하지는 않지만 아이디어를 준다)

@Effect login$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN) 
    .map(toPayload) 
    .switchMap(password => Observable.concat(
     this.loginService.login(passcode) 
      .map(result => this.actions.loginSuccess(value)) 
      .catch((error) => Observable.of(this.loginError(error))), 
     Observable.of(this.actions.navigateHome()) 
    )); 

(d) 기타? 2

시나리오는 요청의 수를 순서대로 할 필요가 경우를 고려하고, 각 요청을 시작으로 우리는 피드백이 사용자에게 제공 할 수 있도록 "상태"를 업데이트 할.

그 라인을 따라 뭔가 썽크의 예 :

다시
multiphaseAction() { 
    return (dispatch) => { 
     dispatch(this.actions.updateStatus('Executing phase 1'); 
     this.request1() 
      .flatMap(result => { 
       dispatch(this.actions.updateStatus('Executing phase 2'); 
       return this.request2(); 
      }) 
      .flatMap(result => { 
       dispatch(this.actions.updateStatus('Executing phase 3'); 
       return this.request3(); 
      }) 
      ... 
    } 
} 

, 무엇이 "올바른"또는 효과의 접근 방식을 사용하여 이것에 대해 갈 방법을 "제안"것입니까?

어떻게 든 일부 .do(this.store.dispatch(this.actions.updateStatus(...)) 추가하는 대신 다른 할 수 무엇을 더에 붙어, 정말 확신이 하나 ... 나뿐만 아니라이 물건을 배우고

+0

시나리오. –

답변

17

탐색 시나리오에 대한 대답은

@Effect navigateHome$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN_SUCCEEDED) 
    .do(this.router.navigate('/home')) 
    .ignoreElements(); 

설명은 B의 대답입니다 : 당신은 LOGIN_SUCCESS에 반응하고, 라우터가 새로운 액션을 반환하지 않기 때문에, 우리는의 전파를 중지해야합니다 우리는 모든 것을 걸러 내고 있습니다. 이 작업의 type 읽으려고 할 때 필터링하는 것을 잊지 경우

, 라우터는 일반적으로 널 포인터 결과 정의되지 않은 값을 줄일 차례로 감속기로 이어질 것이다, undefined를 반환

그것을 해결하는 또 다른 방법은 사용하는 것입니다 https://github.com/ngrx/router-store

앱에 라우터 저장소를 추가하는 방법에 대한 문서를 확인하십시오.

동일한 효과가 이제 이와 같이 보입니다.

import { go } from '@ngrx/router-store'; 

@Effect navigateHome$: any = this.updates$ 
    .whenAction(LoginActions.LOGIN_SUCCEEDED) 
    .map(() => go(['/home'])); 

go 조치는 라우터 감속기 픽업 및 경로 변경을 트리거 라우터 조치를 파견합니다.

+0

Router : Router를 Effect Class에 주입하면 주기적 종속성 오류가 발생합니다. 앱에서 해봤습니까? –

+0

위와 같이 router-store를 대신 사용하십시오. 그렇게하면 라우터를 효과에 주입 할 필요가 없습니다. –

+0

호기심 때문에'ignoreElements'를 사용하여'{dispatch : false}'를 Effects 데코레이터 함수에 넘기는 것의 이점이 있습니까? 예를 들면 :'@Effect ({dispatch : false}) EffectWhichDoesNotReturnAnAction $' –

-1

.

체인의 첫 번째 작업이 완료되었을 때 감속기에 파견 한 경우 어떻게됩니까? 이 같은

뭔가 :

const myReducer = (state,action:Action) => { 
switch action.type { 
case : "my_first_step" : runfirststep(action.payload); 
case : "my_second_step": runsecondstep(action.payload); 
.... 

function runfirststep(data) { 
... 
//bunch of stuff to do, 
//update something to display 
store.dispatch('my_second_step'); 
} 

ngrx 예제는 효과 파일에서이 작업을 수행합니다. 추가 또는 업데이트 할 때 UPDATE_COMPLETE 또는 유사한 것을 호출하므로 일부 알림을 수행 할 수 있습니다.

나는 감속재가 어느 정도 복잡한 앱에 얼마나 큰 결과가 될지 천천히 파악하고 있습니다.

+1

감속기에 상점에 액세스 할 수 없습니다. 감속기가 순수한 기능 즉 가시적 인 부작용이 아님을 기억하십시오. –

+0

실제로. 예제 애플리케이션에서 디스패치 LOAD_COLLECTION은 감속기에서 s 상태를 '대기'로 설정합니다. 이 효과는 상태 변경 및 디스패치를 ​​감지하고 원격 호출로 쿼리를 호출합니다. 콜백에서 이는 쿼리 페이로드로 LOAD_COLLECTION_COMPLETE를 전달합니다.이 페이로드는 대기 상태를 설정하고 데이터를 상태에 제공합니다. –

0

시나리오 1

옵션 A 참조 & B는 모두 내가 생각 갈 수 있습니다,하지만 어쩌면 옵션 A는 약간은 탐색 너무 많이! 이 부작용의 일부로 탐색을 고려한다면 LoginActions.LOGIN에서 라우터를 직접 사용할 수도 있습니다. @Effects을 체인 아무 문제가 없습니다

시나리오 2

. 효과를 트리거하는 작업 (SET_1_REQUEST)을 보냅니다. A. 효과 A는 감속기가 가져온 작업 (SET_1_SUCCESS)을 반환하며이 상태는 사용자에게 표시 될 수 있습니다.이 작업은 효과 B에 의해 선택됩니다.

희망적이라고 생각합니다.

2

시나리오 1

상태를 변경해야하는지 여부를 navigateHome 고려하십시오. 또한이 navigateHome 조치가 동일한 작업을 수행하기 위해 다른 장소에서 발송되었는지 여부에 관계없이 그렇다면 조치를 반환하는 것이 좋습니다. 따라서 옵션 A.

경우에 따라 옵션 B가 더 적합 할 수 있습니다. navigateHome 만 경로를 변경하면 고려해 볼 가치가 있습니다.

사이드 노트 : 여기서 filter(() => false) 대신 ignoreElements을 사용할 수 있습니다.

시나리오 2 내가 여러 효과 여기에 당신의 행동을 체인 및 모든 행동에 대한 감속기 상태를 수정하여 피드백을 제공 제안. 예를 들어

:

@Effect() trigger$: Observable<Action> = this.updates$ 
    .whenAction(Actions.TRIGGER) 
    .do(() => console.log("start doing something here")) 
    .mapTo(Actions.PHASE1); 

@Effect() phase1$: Observable<Action> = this.updates$ 
    .whenAction(Actions.PHASE1) 
    .do(() => console.log("phase 1")) 
    .mapTo(Actions.PHASE2); 

@Effect() phase2$: Observable<Action> = this.updates$ 
    .whenAction(Actions.PHASE2) 
    .do(() => console.log("phase 2")) 
    .ignoreElements(); 

그리고 상태 수정하여 피드백을 제공 : 2 일반 이전 서비스 클래스에 대한 정말 좋은 경우입니다

function reducer(state = initialState, action: Action): SomeState { 
    switch (action.type) { 
     case Actions.TRIGGER: { 
      return Object.assign({}, state, { 
       triggered: true 
      }); 
     } 
     case Actions.PHASE1: { 
      return Object.assign({}, state, { 
       phase1: true 
      }); 
     } 
     case Actions.PHASE2: { 
      return Object.assign({}, state, { 
       phase1: false, 
       phase2: true 
      }); 
     } 
     // ... 
    } 
} 
관련 문제