Redux: 비동기 μž‘μ—…μ„ μ—°κ²°ν•˜λŠ” 방법은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

에 λ§Œλ“  2016λ…„ 04μ›” 28일  Β·  24μ½”λ©˜νŠΈ  Β·  좜처: reduxjs/redux

μ•ˆλ…•ν•˜μ„Έμš”, μ €λŠ” Reduxλ₯Ό κ³΅λΆ€ν•˜κ³  μžˆλŠ”λ° ν₯미둜운 λ¬Έμ œμ— μ§λ©΄ν–ˆμŠ΅λ‹ˆκΉŒ? λ‹€λ₯Έ μž‘μ—…μ—μ„œ 비동기 μš”μ²­ 체인을 λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.
1-getUser()
2-getPost()

둜그인 μ‚¬μš©μž .then(dispatch({type:GET_POST_REQUEST})) ν›„ 2개의 μ†”λ£¨μ…˜μ΄ μ‹€ν–‰λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
λ˜λŠ” middleWareμ—μ„œ κΈ°λŠ₯을 μž‘μ„±ν•˜μ‹­μ‹œμ˜€.

μ˜¬λ°”λ₯΄κ²Œ μˆ˜ν–‰ν•˜λŠ” 방법?

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

μ•ˆλ…•! 이것은 문제 좔적기이며 지원 포럼이 μ•„λ‹™λ‹ˆλ‹€. SO와 달리 μ—¬κΈ°μ—μ„œ 닡을 μžƒμ–΄λ²„λ¦¬κΈ° λ•Œλ¬Έμ— λ‹€μŒ λ²ˆμ— StackOverflow에 μ§ˆλ¬Έν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

즉, Redux Thunk λ―Έλ“€μ›¨μ–΄λ‘œ μŠ€ν† μ–΄λ₯Ό μƒμ„±ν•˜λ©΄ λ‹€μŒκ³Ό 같이 비동기 μž‘μ—… 생성기λ₯Ό μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// If you use Redux Thunk...
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
const store = createStore(reducer, applyMiddleware(thunk))

// You can define asynchronous action creators that return functions.
// We call such action creators "thunks":

export function getUser(id) {
  // Redux Thunk will inject dispatch here:
  return dispatch => {
    // Reducers may handle this to set a flag like isFetching
    dispatch({ type: 'GET_USER_REQUEST', id })

    // Perform the actual API call
    return fetchUser().then(
      response => {
        // Reducers may handle this to show the data and reset isFetching
        dispatch({ type: 'GET_USER_SUCCESS', id,  response })
      },
      error => {
        // Reducers may handle this to reset isFetching
        dispatch({ type: 'GET_USER_FAILURE', id,  error })
        // Rethrow so returned Promise is rejected
        throw error
      }
    )
  }
}

// Thunks can be dispatched, if Redux Thunk is applied,
// just like normal action creators:
store.dispatch(getUser(42));

// The return value of dispatch() when you dispatch a thunk *is*
// the return value of the inner function. This is why it's useful
// to return a Promise (even though it is not strictly necessary):
store.dispatch(getUser(42)).then(() =>
  console.log('Fetched user and updated UI!')
)

// Here is another thunk action creator.
// It works exactly the same way.
export function getPost(id) {
  return dispatch => {
    dispatch({ type: 'GET_POST_REQUEST', id })
    return fetchPost().then(
      response => dispatch({ type: 'GET_POST_SUCCESS', id,  response }),
      error => {
        dispatch({ type: 'GET_POST_FAILURE', id,  error })
        throw error
      }
    )
  }
}

// Now we can combine them
export function getUserAndTheirFirstPost(userId) {
  // Again, Redux Thunk will inject dispatch here.
  // It also injects a second argument called getState() that lets us read the current state.
  return (dispatch, getState) => {
    // Remember I told you dispatch() can now handle thunks?
    return dispatch(getUser(userId)).then(() => {
      // Assuming this is where the fetched user got stored
      const fetchedUser = getState().usersById[userId]
      // Assuming it has a "postIDs" field:
      const firstPostID = fetchedUser.postIDs[0]
      // And we can dispatch() another thunk now!
      return dispatch(getPost(firstPostID))
    })
  }
}

// And we can now wait for the combined thunk:
store.dispatch(getUserAndTheirFirstPost(43)).then(() => {
  console.log('fetched a user and their first post')
})

// We can do this anywhere we have access to dispatch().
// For example, we can use this.props.dispatch, or put action
// creators right into the props by passing them to connect, like this:
// export default connect(mapStateToProps, { getUserAndTheirFirstPost })

이것을 FAQ에 λ„£μ–΄μ•Ό ν•©λ‹ˆλ‹€.

λͺ¨λ“  24 λŒ“κΈ€

μ•ˆλ…•! 이것은 문제 좔적기이며 지원 포럼이 μ•„λ‹™λ‹ˆλ‹€. SO와 달리 μ—¬κΈ°μ—μ„œ 닡을 μžƒμ–΄λ²„λ¦¬κΈ° λ•Œλ¬Έμ— λ‹€μŒ λ²ˆμ— StackOverflow에 μ§ˆλ¬Έν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

즉, Redux Thunk λ―Έλ“€μ›¨μ–΄λ‘œ μŠ€ν† μ–΄λ₯Ό μƒμ„±ν•˜λ©΄ λ‹€μŒκ³Ό 같이 비동기 μž‘μ—… 생성기λ₯Ό μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// If you use Redux Thunk...
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
const store = createStore(reducer, applyMiddleware(thunk))

// You can define asynchronous action creators that return functions.
// We call such action creators "thunks":

export function getUser(id) {
  // Redux Thunk will inject dispatch here:
  return dispatch => {
    // Reducers may handle this to set a flag like isFetching
    dispatch({ type: 'GET_USER_REQUEST', id })

    // Perform the actual API call
    return fetchUser().then(
      response => {
        // Reducers may handle this to show the data and reset isFetching
        dispatch({ type: 'GET_USER_SUCCESS', id,  response })
      },
      error => {
        // Reducers may handle this to reset isFetching
        dispatch({ type: 'GET_USER_FAILURE', id,  error })
        // Rethrow so returned Promise is rejected
        throw error
      }
    )
  }
}

// Thunks can be dispatched, if Redux Thunk is applied,
// just like normal action creators:
store.dispatch(getUser(42));

// The return value of dispatch() when you dispatch a thunk *is*
// the return value of the inner function. This is why it's useful
// to return a Promise (even though it is not strictly necessary):
store.dispatch(getUser(42)).then(() =>
  console.log('Fetched user and updated UI!')
)

// Here is another thunk action creator.
// It works exactly the same way.
export function getPost(id) {
  return dispatch => {
    dispatch({ type: 'GET_POST_REQUEST', id })
    return fetchPost().then(
      response => dispatch({ type: 'GET_POST_SUCCESS', id,  response }),
      error => {
        dispatch({ type: 'GET_POST_FAILURE', id,  error })
        throw error
      }
    )
  }
}

// Now we can combine them
export function getUserAndTheirFirstPost(userId) {
  // Again, Redux Thunk will inject dispatch here.
  // It also injects a second argument called getState() that lets us read the current state.
  return (dispatch, getState) => {
    // Remember I told you dispatch() can now handle thunks?
    return dispatch(getUser(userId)).then(() => {
      // Assuming this is where the fetched user got stored
      const fetchedUser = getState().usersById[userId]
      // Assuming it has a "postIDs" field:
      const firstPostID = fetchedUser.postIDs[0]
      // And we can dispatch() another thunk now!
      return dispatch(getPost(firstPostID))
    })
  }
}

// And we can now wait for the combined thunk:
store.dispatch(getUserAndTheirFirstPost(43)).then(() => {
  console.log('fetched a user and their first post')
})

// We can do this anywhere we have access to dispatch().
// For example, we can use this.props.dispatch, or put action
// creators right into the props by passing them to connect, like this:
// export default connect(mapStateToProps, { getUserAndTheirFirstPost })

이것을 FAQ에 λ„£μ–΄μ•Ό ν•©λ‹ˆλ‹€.

이 문제λ₯Ό λ‹€μŒκ³Ό 같이 ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€. μˆ˜μ • μž‘μ—… 없이. Promise ꡬ성 μš”μ†Œλ₯Ό λ„£μ—ˆμŠ΅λ‹ˆλ‹€.

  clickShowUserEvent(data) {
   Promise.resolve(data.userAuth(data.login, data.password)) // dispatch
    .then(function (response) {
      data.showEvents(); //dispatch
      return response;
    })
    .then(function(response){console.log("@RESPONSE",response);data.show(data)})
  }

이것이 μ˜¬λ°”λ₯Έ κ²°μ •μž…λ‹ˆκΉŒ?

이것은 μ—­μ‹œ μž‘λ™ν•˜λ©° μ–΄λ–€ νŒ¨ν„΄μ„ μ‚¬μš©ν• μ§€λŠ” λ‹Ήμ‹ μ—κ²Œ 달렀 μžˆμŠ΅λ‹ˆλ‹€.

@ar53n React μ»΄ν¬λ„ŒνŠΈμ˜ promiseκ°€ μžˆλŠ” νŒ¨ν„΄μ—λŠ” λͺ‡ 가지 결함이 μžˆμŠ΅λ‹ˆλ‹€.

  • 였λ₯˜ μ²˜λ¦¬κ°€ μ—†μŠ΅λ‹ˆλ‹€( μœ„μ˜ 예 μ—μ„œ), 즉 catch λΆ€λΆ„μž…λ‹ˆλ‹€. μ²˜λ¦¬λ˜μ§€ μ•Šμ€ κ±°λΆ€λ₯Ό 받을 수 μžˆμŠ΅λ‹ˆλ‹€.
  • ꡬ성 μš”μ†Œκ°€ 마운트 ν•΄μ œλ˜κ±°λ‚˜ μ•± μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” 일뢀 μž‘μ—…μ΄ λ°œμƒν•˜λŠ” κ²½μš°μ™€ 같이 쀑단할 수 μ—†μŠ΅λ‹ˆλ‹€.
  • κ·Έ μƒνƒœλŠ” μ•”μ‹œμ μž…λ‹ˆλ‹€. λΆ€μž‘μš©μ€ λ³„λ„μ˜ λ…Όμ˜μ΄μ§€λ§Œ 적어도 μ•± μƒνƒœμ—μ„œ μ‹€ν–‰ 쀑인 ν”„λ‘œμ„ΈμŠ€μ˜ 좔적이 있으면 μœ μš©ν•  κ²ƒμž…λ‹ˆλ‹€.

@sompylasar κ°μ‚¬ν•©λ‹ˆλ‹€ John은 κ·€ν•˜μ˜ μ˜κ²¬μ— κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. κ°„λ‹¨ν•œ μž‘μ—…μ„ μˆ˜μ •ν•˜κ³  싢지 μ•ŠμŠ΅λ‹ˆλ‹€. Authentication 및 GetEvents 2개의 κ°„λ‹¨ν•œ μž‘μ—…μ΄ μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 2개의 비동기 μš”μ²­μ΄λ©° catch 도 ν¬ν•¨ν•©λ‹ˆλ‹€. ꡬ성 μš”μ†Œλ₯Ό ν΄λ¦­ν•˜λ©΄ 이 μž‘μ—…λ§Œ ν˜ΈμΆœλ©λ‹ˆλ‹€.
예

export function userAuth(login, password) {
  return (dispatch, getState) => {
    console.log('STATE', getState())
    let newState = dispatch(requestUserAuth(login, password))
    return fetch(AUTH_URL + newState.queryParams, MY_INIT)
      .then(response => response.json())
      .then(function (json) { dispatch(receiveUserAuth(json)); return json})
      .catch(error => dispatch(errorUserAuth(error)))
  }
}

그리고 μš°λ¦¬λŠ” 이것을 가지고 μžˆμŠ΅λ‹ˆλ‹€
image

λ‚΄κ°€ ν‹€λ Έλ‹€λ©΄ 지적해 μ£Όμ„Έμš”. κ°μ‚¬ν•©λ‹ˆλ‹€.

@ar53n 그러면 λ¬Έμ œκ°€ ν•΄κ²°λ˜κ³  μƒμ μ—μ„œ ν”„λ‘œμ„ΈμŠ€κ°€ μΆ”μ λ©λ‹ˆλ‹€. ꡬ성 μš”μ†Œμ˜ 무쀑단 ν”„λ‘œμ„ΈμŠ€ λ¬Έμ œλŠ” μ—¬μ „νžˆ μ μš©λ˜μ§€λ§Œ ꡬ성 μš”μ†Œ λ˜λŠ” μž‘μ—… μ½ν¬μ—μ„œ μ‹œμž‘ν•œ κ²½μš°μ—λŠ” 그닀지 μ€‘μš”ν•˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

@ar53n redux-dataloader λ₯Ό μ‚΄νŽ΄λ³Ό μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
λ³΅μž‘ν•œ 체인 비동기 μž‘μ—…μ„ μœ„ν•΄ μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
도움이 되기λ₯Ό λ°”λžλ‹ˆλ‹€!

여기에 κ²Œμ‹œλœ λͺ‡ 가지 κ°€λŠ₯ν•œ μ†”λ£¨μ…˜μ΄ μžˆμœΌλ―€λ‘œ 이것을 λ‹«μŠ΅λ‹ˆλ‹€. μš”μ¦˜ redux-sagaλ₯Ό μ‚΄νŽ΄λ³΄κ³  싢을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€!

@gaearon λ‹˜ 의 μ˜ˆμ‹œλŠ” μ‰¬λŠ” μ‹œκ°„ 여행을 ν•˜κ³  μžˆμ§€ μ•ŠμŠ΅λ‹ˆκΉŒ?

예λ₯Ό λ“€μ–΄ AJAX 호좜이 μ²˜μŒμ— μ‹€νŒ¨ν•œ λ‹€μŒ μ„œλ²„ 츑을 μˆ˜μ •ν•˜κ³  λ‹€μ‹œ μ‹€ν–‰ν•˜λ €κ³  ν•©λ‹ˆλ‹€.

@gaearon κ·€ν•˜μ˜ μ†”λ£¨μ…˜μ„ μ‹œλ„ν–ˆμ§€λ§Œ λͺ¨λ“  ꡬ성 μš”μ†Œμ—μ„œ store.dispatch(...) λ₯Ό ν˜ΈμΆœν•˜λ €κ³  ν•  λ•Œ(제 κ²½μš°μ—λŠ” 승인 μš”μ²­μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ LoginComponentμ—μ„œ) λ‹€μŒ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.

undefined is not an object (evaluating '_AppNavigator.AppNavigator.router')

λ­”κ°€ 잘λͺ»λœ 것 κ°™μŠ΅λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 μ•‘μ…˜ 생성기λ₯Ό μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

// actions.tsx
export const ActionCreators = {
    authenticate: (username: string, password: string) => {
        return (dispatch) => {
            return auth.login(username, password).then(
                response => {
                    dispatch(navActionCreators.login(res))
                    return response
                },
                error => {
                    throw error
                }
            )
        }
    }
}

// LoginScreen.tsx (login method)
store.dispatch(authActions.authenticate(this.state.username, this.state.password))
  .then((res) => {
     this.setState({isLoading: false})
   })
   .catch((error: Error) => {
     this.setState({
       isLoading: false,
       error: error ? error.message : 'Si Γ¨ verificato un\' errore.'
     })
   })

λ‚΄κ°€ 무엇을 λ†“μΉ˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

@bm-software: λŒ€μ‹  μŠ€νƒ μ˜€λ²„ν”Œλ‘œμ—μ„œ ν•΄λ‹Ή μ§ˆλ¬Έμ„ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

@ar53n 및 @sompylasar 였랜 μ‹œκ°„μ΄ μ§€λ‚¬μ§€λ§Œ μ§€κΈˆμ€ 이 νŒ¨ν„΄μœΌλ‘œ 어렀움을 κ²ͺκ³  μžˆμŠ΅λ‹ˆλ‹€. κ·€ν•˜μ˜ μ˜ˆμ—μ„œ @ar53n userAuth fetch $κ°€ μ‹€νŒ¨ν•˜λ©΄ userAuth κ°€ ν˜ΈμΆœλ˜λŠ” μ²΄μΈμ—μ„œ μ–΄λ–€ 일이 λ°œμƒν•©λ‹ˆκΉŒ?

.catch(error => dispatch(errorUserAuth(error))) κ°€ errerUserAuth μž‘μ—…μ„ μ „λ‹¬ν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€. ν›Œλ₯­ν•©λ‹ˆλ‹€. Reduxμ—μ„œ 이것은 일반적으둜 였λ₯˜λ₯Ό "처리"ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ•žμ„œ μ–ΈκΈ‰ν•œ μ²΄μΈμ—μ„œ:

clickShowUserEvent(data) {
   Promise.resolve(data.userAuth(data.login, data.password)) // dispatch
    .then(function (response) {
      data.showEvents(); //dispatch
      return response;
    })
    .then(function(response){console.log("@RESPONSE",response);data.show(data)})
  }

data.showEvents() λŠ” μ‚¬μš©μž 인증이 μ‹€νŒ¨ν•˜λ”λΌλ„ _항상_ ν˜ΈμΆœλ©λ‹ˆλ‹€. λ‚˜λŠ” 그것이 λŒ€λΆ€λΆ„μ˜ μ‚¬λžŒλ“€μ΄ κΈ°λŒ€ν•˜κ±°λ‚˜ μ›ν•˜λŠ” 것이라고 μƒκ°ν•˜μ§€ μ•Šμ§€λ§Œ Redux의 였λ₯˜ μ²˜λ¦¬λŠ” 일반적으둜 re-throwκ°€ μ•„λ‹Œ β€‹β€‹λ””μŠ€νŒ¨μΉ˜λ‘œ μˆ˜ν–‰λ˜κΈ° λ•Œλ¬Έμ— 였λ₯˜λ₯Ό μ‚Όν‚€λ―€λ‘œ 약속 체이닝이 μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ˜ν•œ λ‹€μ‹œ λ˜μ§€λ©΄ _μ–΄λ””μ„œλ‚˜ μ•±μ˜ λͺ¨λ“  단일 μž‘μ—… μƒμ„±μž ν˜ΈμΆœμ—μ„œ .catch() λ₯Ό ν•΄μ•Ό ν•©λ‹ˆλ‹€. λͺ¨λ“  였λ₯˜λ₯Ό λ‹€μ‹œ λ˜μ§„ μœ„μ˜ @gaearon μ˜ˆμ œλŠ” λ§ˆμ§€λ§‰μ— λ‹€μŒμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

// And we can now wait for the combined thunk:
store.dispatch(getUserAndTheirFirstPost(43)).then(() => {
  console.log('fetched a user and their first post')
})

getUserAndTheirFirstPost λ‚΄λΆ€μ˜ 큰 κ²°ν•© μ²΄μΈμ—μ„œ _anything_이 μ‹€νŒ¨ν•˜λ©΄ "μ²˜λ¦¬λ˜μ§€ μ•Šμ€ 약속 κ±°λΆ€" 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

μœ μΌν•œ 닡은 λͺ¨λ“  κ³³μ—μ„œ λ‹€μ‹œ λ˜μ§„ λ‹€μŒ .catch() λ₯Ό λ‹€μ‹œ λ˜μ§€κ±°λ‚˜ React 16 였λ₯˜ 경계λ₯Ό μ‚¬μš©ν•˜λŠ” 것이라고 μƒκ°ν•©λ‹ˆλ‹€.

@jasonrhodes

clickShowUserEvent(data) {
   Promise.resolve(data.userAuth(data.login, data.password)) // dispatch
    .then(function (response) {
      data.showEvents(); //dispatch

data.showEvents() λŠ” μ‚¬μš©μž 인증이 μ‹€νŒ¨ν•˜λ”λΌλ„ _항상_ ν˜ΈμΆœλ©λ‹ˆλ‹€.

μ•„λ‹ˆμš”, data.userAuth(data.login, data.password) κ°€ κ²°κ΅­ κ±°λΆ€λ˜λŠ” 약속을 λ°˜ν™˜ν•˜λ©΄ ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. .then 에 λŒ€ν•œ 첫 번째 μΈμˆ˜λŠ” 약속이 이행될 λ•Œ 호좜되고( onFulfilled 라고 함), 두 번째 μΈμˆ˜λŠ” 약속이 거뢀될 λ•Œ ν˜ΈμΆœλ©λ‹ˆλ‹€( onRejected ) – 사양 μ°Έμ‘° .

λ°˜λ©΄μ— React 16 였λ₯˜ κ²½κ³„λŠ” promise에 도움이 λ˜μ§€ μ•ŠμœΌλ©° React λ‚΄λΆ€ μƒνƒœκ°€ 깨지지 μ•Šλ„λ‘ λ™κΈ°μ μœΌλ‘œ λ°œμƒν•œ μ˜ˆμ™Έλ§Œ catchν•©λ‹ˆλ‹€.

@jasonrhodes λ˜ν•œ Promise μ„Έκ³„μ˜ 쒋은 μ‹œλ―Όμ΄ λ˜μ‹­μ‹œμ˜€. ν˜ΈμΆœμžμ—κ²Œ 약속을 λ°˜ν™˜ν•˜κ±°λ‚˜(그런 λ‹€μŒ 였λ₯˜λ₯Ό μ²˜λ¦¬ν•΄μ•Ό 함) .catch λ₯Ό 첨뢀(그리고 약속이 μƒμ„±λœ 였λ₯˜λ₯Ό 처리)ν•©λ‹ˆλ‹€.

κ·€ν•˜μ˜ μ˜ˆλŠ” 아무 κ²ƒλ„ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

clickShowUserEvent(data) {
   Promise.resolve(data.userAuth(data.login, data.password)) // dispatch
    .then(function (response) {
      data.showEvents(); //dispatch
      return response;
    })
    .then(function(response){console.log("@RESPONSE",response);data.show(data)})
  }

@sompylasar 그것은 λ‚΄ μ˜ˆκ°€ μ•„λ‹ˆλΌ 이 μŠ€λ ˆλ“œμ˜ μ•žλΆ€λΆ„μ—μ„œ μ‘λ‹΅ν–ˆλ˜ κ²ƒμž…λ‹ˆλ‹€. μ‹œκ°„μ΄ 많이 μ§€λ‚¬λ‹€λŠ” 것을 μ•Œκ³  μžˆμ§€λ§Œ Google 검색을 톡해 이 μŠ€λ ˆλ“œλ₯Ό 두 번 이상 μ ‘ν–ˆκΈ° λ•Œλ¬Έμ— μ—¬κΈ°μ—μ„œ 이전 λŒ€ν™”λ₯Ό μ°Έμ‘°ν–ˆμŠ΅λ‹ˆλ‹€.

λ‹€μ‹œ 보면 userAuth fetch 호좜이 μ‹€νŒ¨ν•˜λ”λΌλ„ data.showEvents() λŠ” _항상_ ν˜ΈμΆœλ©λ‹ˆλ‹€. μ™œμš”? userAuth ν•¨μˆ˜ 내뢀에 Redux λ°©μ‹μœΌλ‘œ 였λ₯˜λ₯Ό μ²˜λ¦¬ν•˜λŠ” .catch() κ°€ 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

이것이 λ‚΄ κ²Œμ‹œλ¬Όμ˜ μš”μ μž…λ‹ˆλ‹€. 비동기 μž‘μ—…μ—μ„œ 였λ₯˜λ₯Ό ν¬μ°©ν•˜μ—¬ 였λ₯˜ μž‘μ—…μ„ 전달할 λ•Œ 더 μ΄μƒμ˜ 약속 체인이 μ˜¬λ°”λ₯΄κ²Œ μž‘λ™ν•˜μ§€ μ•Šλ„λ‘ μ‚Όν‚€κ³  λ°©μ§€ν•©λ‹ˆκΉŒ? μ•„λ‹ˆλ©΄ "μ²˜λ¦¬λ˜μ§€ μ•Šμ€ 약속 κ±°λΆ€"λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ 무엇을 ν•˜λ“  ν•΄λ‹Ή μž‘μ—… μž‘μ„±μžμ˜ λͺ¨λ“  호좜자λ₯Ό λ‹€μ‹œ λ˜μ§€κ³  κ°•μ œλ‘œ .catch() ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?

λ˜ν•œ λ‚΄ κ²½ν—˜μ— λ”°λ₯΄λ©΄ λˆ„κ΅°κ°€λ₯Ό 사양에 μ—°κ²°ν•˜κΈ° 전에 λˆ„κ΅°κ°€κ°€ μ•Œκ³  μžˆλŠ” 것을 μ΄ν•΄ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 응닡해 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. μ œκ°€ νŒŒν—€μΉœ 였래된 λŒ€ν™”λΌλŠ” 것을 μ•Œκ³  μžˆμ§€λ§Œ μ–Όλ§ˆλ‚˜ λ†“μΉ˜κΈ° μ‰¬μš΄μ§€ μ•Œ 수 μžˆλ“―μ΄ μ€‘μš”ν•œ λŒ€ν™”μž…λ‹ˆλ‹€!

@jasonrhodes

@sompylasar 그것은 λ‚΄ μ˜ˆκ°€ μ•„λ‹ˆλΌ 이 μŠ€λ ˆλ“œμ˜ μ•žλΆ€λΆ„μ—μ„œ μ‘λ‹΅ν–ˆλ˜ κ²ƒμž…λ‹ˆλ‹€. μ‹œκ°„μ΄ 많이 μ§€λ‚¬λ‹€λŠ” 것을 μ•Œκ³  μžˆμ§€λ§Œ Google 검색을 톡해 이 μŠ€λ ˆλ“œλ₯Ό 두 번 이상 μ ‘ν–ˆκΈ° λ•Œλ¬Έμ— μ—¬κΈ°μ—μ„œ 이전 λŒ€ν™”λ₯Ό μ°Έμ‘°ν–ˆμŠ΅λ‹ˆλ‹€.

μ•Œκ² μŠ΅λ‹ˆλ‹€. μ£„μ†‘ν•©λ‹ˆλ‹€. 전체 λ§₯락을 κΈ°μ–΅ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.

userAuth ν•¨μˆ˜ 내뢀에 Redux λ°©μ‹μœΌλ‘œ 였λ₯˜λ₯Ό μ²˜λ¦¬ν•˜λŠ” .catch() κ°€ 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

μ•Œκ² μŠ΅λ‹ˆλ‹€. 그러면 이것이 μ˜λ„ν•œ λŒ€λ‘œ μž‘λ™ν•˜κ±°λ‚˜ ν•΄λ‹Ή 약속을 λ°˜ν™˜ν•˜κ³  호좜 μ‚¬μ΄νŠΈμ—μ„œ 였λ₯˜λ₯Ό μ²˜λ¦¬ν•˜λŠ” 경우 .catch λ₯Ό 거기에 λ‘μ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€. 그렇지 μ•ŠμœΌλ©΄ $ .catch 내에 였λ₯˜λ₯Ό λ‹€μ‹œ λ˜μ Έμ•Ό ν•©λ‹ˆλ‹€.

μ–΄μ¨Œλ“  썽크 μžμ²΄λŠ” 연결에 μ ν•©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 썽크 λ‚΄λΆ€μ—μ„œ μ—°κ²°ν•˜κ±°λ‚˜ 보닀 λ³΅μž‘ν•œ 비동기식 μ›Œν¬ν”Œλ‘œμ— sagasλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‚˜λŠ” μž μ‹œ λ™μ•ˆ 약속 μ‚¬μŠ¬μ„ κΉ¨λŠ” λ¬Έμ œμ— λ§€λ‹¬λ ΈμŠ΅λ‹ˆλ‹€. 일반적으둜 λ‚΄ μž‘μ—… μž‘μ„±μžλŠ” μ½ν¬μ—μ„œ λ°˜ν™˜λœ λ™μΌν•œ http μš”μ²­μ˜ .then()μ—μ„œ SUCCESS μž‘μ—…μ„ λ‚΄λ³΄λ‚΄κ±°λ‚˜ .catch()μ—μ„œ FAILURE μž‘μ—…μ„ λ‚΄λ³΄λƒ…λ‹ˆλ‹€.

λ‚΄ μž‘μ—… μƒμ„±μžκ°€ catch λΈ”λ‘μœΌλ‘œ μ΄λ™ν•˜κ³  λ‚΄κ°€ this.props.myActionCreator().then(() => ) 을 ν•  λ•Œλ§ˆλ‹€ then λ‚΄λΆ€μ˜ μ½”λ“œλŠ” μš”μ²­μ— λ¬Έμ œκ°€ μžˆλ”λΌλ„ μ‹€ν–‰λ©λ‹ˆλ‹€.

이λ₯Ό μ„€λͺ…ν•˜κΈ° μœ„ν•΄ μ €λŠ” 항상 ν•΄λ‹Ή μž‘μ—… μƒμ„±μžμ˜ FAILURE 사둀에 μ„€μ •λœ μ•± μƒνƒœμ˜ 였λ₯˜ λ³€μˆ˜λ₯Ό ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ—¬λŸ¬ μ•‘μ…˜ μ œμž‘μž, 특히 λ‹€λ₯Έ μ‚¬λžŒμ—κ²Œ μ˜μ‘΄ν•˜λŠ” μ œμž‘μžλ₯Ό ν˜ΈμΆœν•˜λ©΄ 상황이 λ³΅μž‘ν•΄μ§‘λ‹ˆλ‹€. λ§Žμ€ 였λ₯˜ λ³€μˆ˜λ₯Ό ν™•μΈν•˜λŠ” if 문이 μžˆμ–΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

μ•‘μ…˜ μƒμ„±μž λ°˜ν™˜ 값에 λŒ€ν•œ catch λΈ”λ‘μ—μ„œ 였λ₯˜λ₯Ό λ‹€μ‹œ throwν•˜μ—¬ 약속 체인을 κΉ¨λœ¨λ¦¬μ§€ μ•ŠλŠ”λ‹€λŠ” 사싀이 λ§ˆμŒμ— λ“­λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이λ₯Ό μœ„ν•΄μ„œλŠ” μ•‘μ…˜ μƒμ„±μžκ°€ ν˜ΈμΆœλ˜λŠ” React ꡬ성 μš”μ†Œμ—μ„œ .catch()λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 였λ₯˜ λ³€μˆ˜κ°€ κ°μ†κΈ°μ—μ„œ FAILURE μž‘μ—…μ„ μ²˜λ¦¬ν•˜μ—¬ 이미 μ„€μ •λ˜μ–΄ 있기 λ•Œλ¬Έμ— ν•΄λ‹Ή catch 블둝에 아무 것도 μž‘μ„±ν•˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

@jasonrhodes , @sompylasar μ—¬λŸ¬λΆ„, λ‹€μ‹œ λ˜μ§€λŠ” μ ‘κ·Ό 방식을 μ‚¬μš©ν•˜κ³  React ꡬ성 μš”μ†Œμ—μ„œ μž‘μ—… μƒμ„±μž 호좜의 약속 체인에 빈 .catch() 블둝을 λ°°μΉ˜ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

@nbkhope μ†”μ§νžˆ λ§ν•΄μ„œ 이것이 Redux의 κ°€μž₯ 큰 λ¬Έμ œμ˜€μœΌλ©° μ§€κΈˆκΉŒμ§€ 쒋은 닡을 찾지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. 더 도움이 λ˜μ§€ λͺ»ν•΄ μ£„μ†‘ν•©λ‹ˆλ‹€!

μ—¬λŸ¬λΆ„, 이 κΈ°μ‚¬μ—μ„œ 썽크 λŒ€μ•ˆμ„ 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. https://decembersoft.com/posts/what-is-the-right-way-to-do-asynchronous-operations-in-redux/

@gaearon

첫 번째 λ‹΅λ³€κ³Ό κ΄€λ ¨ν•˜μ—¬ 약속 λŒ€μ‹  비동기 및 λŒ€κΈ°λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μ–΄λ–»κ²Œ λ³€ν™˜ν•΄μ•Ό ν•©λ‹ˆκΉŒ? λ‹€μŒκ³Ό 같은 것:

export const funcA = () => {
    return async (dispatch) => {
        const data = await doSomething(...)
        dispatch({ action: DID_SOMETHING, payload: data })
    }
}

export const funcB = () => {
    return async (dispatch) => {
        const data = await doSomethingElse(...)
        dispatch({ action: DID_SOMETHING_ELSE, payload: data })
    }
}

export const funcC = () => {
    return async (dispatch) => {
        const data = await doSomethingMore(...)
        dispatch({ action: DID_SOMETHING_MORE, payload: data })
    }
}

// how to chain funcA, funcB and funcC
const myFunc = () => {
    // execute funcA
    // when complete execute funcB
    // when complete execute funcC
}

@yingdongzhang λ‹€μŒκ³Ό 같이 μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

const myFunc = () => {
  return async (dispatch) => {
    try {
      await dispatch(funcA())
      await dispatch(funcB())
      await dispatch(funcC())
    } catch (error) {
      //error handling
    }
  }
}

@Boomxx κ°μ‚¬ν•©λ‹ˆλ‹€ μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•©λ‹ˆλ‹€.

fetch all posts of the user 을 μ–΄λ–»κ²Œ ν•΄μ•Ό ν•˜λŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

@km16 : 이것은 지원 μ‹œμŠ€ν…œμ΄ μ•„λ‹Œ 버그 μΆ”μ κΈ°μž…λ‹ˆλ‹€. μ‚¬μš©λ²•μ— κ΄€ν•œ μ§ˆλ¬Έμ€ Stack Overflow λ˜λŠ” Reactifluxλ₯Ό μ‚¬μš©ν•˜μ—¬ 도와쀄 μ€€λΉ„κ°€ 된 더 λ§Žμ€ μ‚¬λžŒλ“€μ΄ μžˆμŠ΅λ‹ˆλ‹€. 더 λ‚˜μ€ 닡변을 더 빨리 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. 감사 ν•΄μš”!

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰