2017-05-08 6 views
1

코드재시도 기능 나는 다음과 같은 한 내 응용 프로그램에서

componentWillUpdate(nextProps) { 
    if(nextProps.posts.request.status === 'failed') { 
    let timer = null; 

    timer = setTimeout(() => { 
     if(this.props.posts.request.timeOut == 1) { 
     clearTimeout(timer); 
     this.props.fetchData({ 
      page: this.props.posts.request.page 
     }); 
     } else { 
     this.props.decreaseTimeOut(); 
     } 
    }, 1000); 
    } 
} 

그 것이다 무엇을, 그 방법 페이스 북의 채팅 작품처럼 어떤 인터넷 연결이 (가 없기 때문에 API 요청은 아마 오류가 발생하는 경우) 또는 백엔드에 오류가있는 경우 5 초 후에 다시 시도하지만 매장의 일부 (예 : this.props.decreaseTimeOut();)를 업데이트하려면 setTimeout을 1 초마다 설정해야하지만 카운터가 실행 된 경우 5 초가 지나면 if block이 실행되어 fetchData action을 재실행합니다.

잘 작동하며 기능면에서는별로 문제가 없지만 코드 디자인 측면에서 보면 side-effect이라는 것을 알고 있으며 내 반응 구성 요소에서 처리하면 안됩니다. 나는 redux-saga를 사용하고 있습니다. (그러나 저는 redux-saga에 익숙하지 않습니다. 오늘 방금 배웠습니다.) 나는 그 기능을 무용담으로 바꾸고 싶습니다. 아직 어떻게 할 것인가에 대해서는 아직 생각이 없습니다. 그리고 여기에 내 fetchData saga입니다.

import { 
    take, 
    call, 
    put 
} from 'redux-saga/effects'; 

import axios from 'axios'; 

export default function* fetchData() { 
    while(true) { 
    try { 
     let action = yield take('FETCH_DATA_START'); 
     let response = yield call(axios.get, '/posts/' + action.payload.page); 
     yield put({ type: 'FETCH_DATA_SUCCESS', items: [...response.data.items] }); 
    } catch(err) { 
     yield put({ type: 'FETCH_DATA_FAILED', timeOut: 5 }); 
    } 
    } 
} 

답변

2

코드 REDUX-사가에서 delay 약속 사용에 대한 덜 관입 일 :이 방법으로 코드를 리팩토링 것

catch(err) { 
    yield put({ type: 'FETCH_DATA_FAILED'}); 

    for (let i = 0; i < 5; i++) { 
     yield call(delay, 1000); 
     yield put(/*Action for the timeout/*); 
    } 
} 

그러나 :

function* fetchData(action) { 
    try { 
     let response = yield call(axios.get, '/posts/' + action.payload.page); 
     yield put({ type: 'FETCH_DATA_SUCCESS', items:[...response.data.items] }); 
    } catch(err) { 
     yield put({ type: 'FETCH_DATA_FAILED'}); 
     yield put({ type: 'SET_TIMEOUT_SAGA', time: 5 }); 
    } 
    } 
} 

function *setTimeoutsaga(action) { 
    yield put({type: 'SET_STATE_TIMEOUT', time: action.time}); // Action that update your state 
    yield call(delay, 1000); 

    // Here you use a selector which take the value if is disconnected: 
    // https://redux-saga.js.org/docs/api/#selectselector-args 
    const isStillDisconnected = select() 
    if (isStillDisconnected) { 
     yield put({type: 'SET_TIMEOUT_SAGA', time: action.time - 1}); 
} 

function *fetchDataWatchers() { 
    yield takeEvery('FETCH_DATA_START', fetchData); 
    yield takeEvery('SET_TIMEOUT_SAGA', setTimeoutSaga); 

    // You can insert here as many watcher you want 
} 

export default [fetchDataWatchers]; // You will use run saga for registering this collection of watchers 
+0

보이는을 awesome하지만 필자는 FETCH_DATA_START에 takeEvery를 사용하고 싶지 않습니다. 사용자가 '데이터 가져 오기 버튼'을 계속 클릭하여 여러 요청을 반복해서 보내고 싶지 않기 때문에 요청 만 보냅니다. 한 번에 하나씩 나는 테이크를 사용했습니다. 그렇게 나쁘지 않습니까? –

+0

@ four-eyes-04-04 그러면 정확히 필요한 작업을 수행하는'takeLatest'를 사용할 수 있습니다 :) 어쨌든 코드는 괜찮습니다. while while true 구조가 마음에 들지 않지만 원하는 경우 그 첫 번째 스 니펫에서 제안한대로 '지연'을 사용하십시오. – rpadovani

+0

제안 해 주셔서 감사합니다. 기능을 성공적으로 구현할 수있었습니다. :-) –