웹사이트 검색

javascript - Redux 프로미스 오류를 디스패치에서 잡아야 하나요, 아니면 리듀서에서 처리하기만 하면 되나요?


기본적으로 저는 thunk와 redux-promise-middleware를 사용하여 액션을 디스패치하고 있으며, 이는 프로미스를 반환하는 API 호출을 수행합니다. 그런 다음 반환된 프로미스를 다른 액션 생성자에게 'payload' 인수로 보내면, redux-promise-middleware가 이를 처리하고 MY_ACTION_TYPE_PENDING, MY_ACTION_TYPE_REJECTED 또는 MY_ACTION_TYPE_FULFILLED와 같은 다양한 액션을 처리합니다. 제 질문은, 이 경우 오류를 리듀서에서 _REJECTED 액션을 통해 처리하고 dispatch(actionCreator(payload))에서 catch하지 않는 것이 맞는지에 대한 것입니다. dispatch에서 오류를 catch하지 않으면, 리듀서가 _REJECTED 액션으로 오류를 잘 처리함에도 불구하고 콘솔에 경고가 나타납니다.

다음은 나의 몇 가지 행동입니다:

export const RECEIVE_POSTS = 'RECEIVE_POSTS';
export const receivePosts = (data) => ({
    type: RECEIVE_POSTS,
    payload: data
})

// thunk middleware for fetching blog
                    export const fetchPosts = () => { 
                        return (dispatch) => {
                            const payload = contentfulClient.getEntries().then(
                                data => data.items,
                                error => console.log('An error occurred in fetchPost thunk middleware', error)
                                ) 
                            return dispatch(receivePosts(payload))
                            .catch((error) => {
                                console.log('caught error in fetchPost', error)
                            })
                        }
                    }

그럼 이것은 내 블로그 리듀서 파일 중 일부로, 프로미스 미들웨어가 보내는 액션들을 처리합니다

const status = (state = Status.IDLE, action) => {
    switch (action.type) {
        case `${RECEIVE_POSTS}_PENDING` : 
            return Status.PENDING;      
        case `${RECEIVE_POSTS}_FULFILLED`:
            return Status.FULFILLED;
        case `${RECEIVE_POSTS}_REJECTED`:
            return Status.REJECTED;
        default:
            return state
    }
}

const error = (state = null, action) => {
    switch (action.type) {
    case `${RECEIVE_POSTS}_REJECTED`: 
        return action.payload.message
    default:
        return state;
    }
}

답변 #1

좋은 질문이며, 하나의 정답이 있다고 생각하지 않습니다. 궁극적으로 이는 개발자나 개발 팀에게 달려 있습니다. 개인적인 관점으로는, 네, 약속(promise) 오류는 디스패치(dispatch) 시 처리/포착되어야 한다고 주장하고 싶습니다. 이유는 다음과 같습니다...

예제에서, 당신은 프로미스 오류를 잡지 않습니다. 설명한 것처럼, 당신은 리듀서에서만 오류를 처리합니다.

case `${RECEIVE_POSTS}_REJECTED`:
            return Status.REJECTED;

당신은 $ {RECEIVE_POSTS}_REJECTED 타입의 객체를 읽고 상태에 변경 사항을 기록합니다. 상태에 변경 사항을 기록할 때, 당신은 (아마도 UI를 업데이트하거나 오류를 처리하기 위해 부수 효과를 디스패치할 것입니다. 이는 Redux의 일반적인 구현 방식입니다.

그러나 실제 약속(promise)은 이 구현에서는 잡히지 않습니다. 약속 오류를 잡으려면, 디스패치(dispatch) 시점에 하거나 미들웨어에서 해야 합니다.

dispatch(myAsyncActionCreator()).catch(function(error) {
  // do something with the error
})

만약 디스패치 시점에서 오류를 잡는다면, 콘솔에서 오류를 볼 수 없을 것입니다. 장황하지만 명확하고 직접적인 이 방법은 다른 개발자들에게 오류가 어떻게 처리되는지를 분명히 보여줍니다. 저는 유지보수성과 미래의 변경을 위해 명확성이 중요하다고 믿기 때문에, 디스패치 시점에서 오류를 잡는 것을 주장합니다.

도움이 되길 바래요!

답변 #2

저는 redux-promise-middleware의 자동 타입 수정보다 redux-thunk 코드를 따라가는 것이 더 이해하기 쉽다고 생각합니다... 그래서 다른 사람들도 비교가 유용하다고 느낄 경우에 대비해 대안으로 게시합니다:

export const fetchPosts = () => (dispatch) => {
  dispatch({type: '${RECEIVE_POSTS}_PENDING'})
  contentfulClient.getEntries()
    .then(data => dispatch({type: '${RECEIVE_POSTS}_FULFILLED', payload: data.items})
    .catch(error => dispatch({type: '${RECEIVE_POSTS}_REJECTED', payload: error})})
}