IT이야기

환원 관측 가능에서 여러 작업을 전송하는 방법?

cyworld 2022. 4. 9. 08:57
반응형

환원 관측 가능에서 여러 작업을 전송하는 방법?

나는 환원 관측할 수 있는 서사시에서 여러 가지 행동을 파견하고 싶다.어떻게 하면 좋을까?나는 원래부터 시작했다.

const addCategoryEpic = action$ => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      return db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })
        .then(() => {
          return { type: ADD_CATEGORY_SUCCESS }
        })
        .catch(err => {
          return { type: ADD_CATEGORY_ERROR, payload: err }
        })
    })
}

이제 단순한 파견이 아닌ADD_CATEGORY_SUCCESS, 목록도 새로 고치고 싶다(GET_CATEGORIES_REQUEST많은 것을 시도했지만 항상 얻어진다.

행동은 평범한 물건이어야 한다.비동기 작업에 사용자 지정 미들웨어 사용

예를 들면 다음과 같다.

const addCategoryEpic = action$ => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      return db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })
        .then(() => {
          return Observable.concat([
            { type: ADD_CATEGORY_SUCCESS },
            { type: GET_CATEGORIES_REQUEST }
          ])
        })
        .catch(err => {
          return { type: ADD_CATEGORY_ERROR, payload: err }
        })
    })
}

아니면 변화한다switchMapmergeMap

문제는 네 안에 있다는 거야switchMap당신은 그 자체가 관찰할 수 있는 것으로 결정되는 약속을 반환할 것이다.Promise<ConcatObservable> . .switchMap후 그 운자자에게 이다.store.dispatch환원성 섬유로 덮인 rootEpic(action$, store).subscribe(store.dispatch)관찰 하는 것은이 되지 않기 행동이 를 얻게 관찰 가능을 파견하는 것은 말이 되지 않기 때문에, 행동이 반드시 평범한 물체여야 한다는 오류를 얻게 되는 것이다.

당신의 서사시가 배출하는 것은 항상 평범한 자바스크립트 행동 객체여야 한다. { type: string }(다른 작업을 처리할 추가 미들웨어가 없는 경우)

약속은 단 하나의 가치만을 발산하기 때문에, 우리는 그것들을 두 가지 행동을 발산하는데 사용할 수 없기 때문에, 우리는 관찰할 수 있는 것들을 사용해야 한다.그러므로 먼저 우리의 약속을 다음 사항과 함께 작업할 수 있는 관찰 가능으로 전환하자.

const response = db.collection('categories')
  .doc()
  .set({
    name: action.payload.name,
    uid: user.uid
  })

// wrap the Promise as an Observable
const result = Observable.from(response)

이제 우리는 단일 값을 방출할 관찰 가능을 여러 가지 동작으로 매핑해야 한다.map오퍼레이터가 일대다 작업을 수행하지 않고 대신 다음 중 하나를 사용하십시오.mergeMapswitchMapconcatMap또는exhaustMap 이 우리가 을 적용하고하고, 그 엔 완성될 것이기 때문이다 이 매우 구체적인 경우, 우리가 어떤 것을 선택하는지는 중요하지 않다. 왜냐하면 우리가 그것을 적용하고 있는 관찰 가능은 오직 하나의 값만 발산하고 그 다음에는 완료()를 할 것이기 때문이다.그렇긴 하지만, 이러한 운영자들 간의 차이를 이해하는 것이 중요하므로, 확실히 그것들을 연구하는데 시간이 좀 걸릴 것이다.

나는 사용할 것이다mergeMap(이 경우, 이 경우 중요하지 않다.)이후mergeMap한다. 는 '스트림'(stream)을 한다Observable.of우리가 내보내고 싶은 두 가지 행동을 관찰할 수 있게 만드는 것이다.

Observable.from(response)
  .mergeMap(() => Observable.of(
    { type: ADD_CATEGORY_SUCCESS },
    { type: GET_CATEGORIES_REQUEST }
  ))

이 두 가지 행동은 내가 제공한 순서대로 동시에 순차적으로 방출될 것이다.

오류 처리도 다시 추가해야 하니, 다음 사항을 활용하도록 하겠다.catchRxJS로부터 연산자--그것과 그것 사이의 차이catch약속에 대한 방법은 중요하지만, 이 질문의 범위를 벗어난다.

Observable.from(response)
  .mergeMap(() => Observable.of(
    { type: ADD_CATEGORY_SUCCESS },
    { type: GET_CATEGORIES_REQUEST }
  ))
  .catch(err => Observable.of(
    { type: ADD_CATEGORY_ERROR, payload: err }
  ))

모두 종합해 보면 다음과 같은 것을 얻을 수 있을 것이다.

const addCategoryEpic = action$ => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      const response = db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })

      return Observable.from(response)
        .mergeMap(() => Observable.of(
          { type: ADD_CATEGORY_SUCCESS },
          { type: GET_CATEGORIES_REQUEST }
        ))
        .catch(err => Observable.of(
          { type: ADD_CATEGORY_ERROR, payload: err }
        ))
    })
}

이것이 작용하고 질문에 답하는 동안, 복수의 환원기는 동일한 단일 동작으로부터 상태를 변화시킬 수 있는데, 이것은 가장 흔히 그 대신 해야 할 일이다.순차적으로 두 가지 동작을 발산하는 것은 대개 안티패턴이다.

그렇긴 하지만 프로그래밍에서 흔히 볼 수 있듯이 이것은 절대적인 규칙이 아니다.분명히 별개의 행동을 하는 것이 더 이치에 맞는 경우가 있지만, 예외적인 경우가 있다.당신은 이것이 그러한 예외적인 사례들 중 하나인지 아닌지를 알 수 있는 더 나은 위치에 있다.그냥 명심해.

Observable.concat을 사용하는 이유는?스위치맵은 콜백 함수의 값(우리의 경우 동작 배열)을 포함하는 관찰 가능 또는 약속을 기다린다.따라서 반환된 약속 성공 담당자에게 관찰 가능을 반환할 필요가 없다. 이 방법을 사용해 보십시오.

const addCategoryEpic = action$ => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      return db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })
        .then(() => {
          return ([
            { type: ADD_CATEGORY_SUCCESS },
            { type: GET_CATEGORIES_REQUEST }
          ])
        })
        .catch(err => {
          return { type: ADD_CATEGORY_ERROR, payload: err }
        })
    })
}

RxJs6의 경우:

action$.pipe(
  concatMap(a => of(Action1, Action2, Action3))
)

참고:concatMap,mergeMap그리고switchMap그것이 그 일을 할 수 있을 것이다. 차이점: https://www.learnrxjs.io/operators/transformation/mergemap.html

당신은 또한 당신의 epic 안에 있는 store를 사용해 볼 수도 있다.

const addCategoryEpic = (action$, store) => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      const query = db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })
       return Observable.fromPromise(query)
    }).map((result) => {
      store.dispatch({ type: ADD_CATEGORY_SUCCESS });
      return ({ type: GET_CATEGORIES_REQUEST })
   })
  .catch(err => {
     return { type: ADD_CATEGORY_ERROR, payload: err }
   })
}

나는 내가 관찰할 수 있는 것을 창조하는 것을 사용해야 한다는 것을 알았다.Observable.fromPromise그 다음에 사용하다flatMap여러 가지 행동을 하다

const addCategoryEpic = action$ => {
  return action$.ofType(ADD_CATEGORY_REQUEST)
    .switchMap((action) => {
      const db = firebase.firestore()
      const user = firebase.auth().currentUser
      const query = db.collection('categories')
        .doc()
        .set({
          name: action.payload.name,
          uid: user.uid
        })
      return Observable.fromPromise(query)
        .flatMap(() => ([
          { type: ADD_CATEGORY_SUCCESS },
          { type: GET_CATEGORIES_REQUEST }
        ]))
        .catch(err => {
          return { type: ADD_CATEGORY_ERROR, payload: err }
        })
    })
}

참조URL: https://stackoverflow.com/questions/47965184/how-to-dispatch-multiple-actions-from-redux-observable

반응형