2017-05-08 13 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); 
    } 
} 

それは何、そのどのようにFacebookのチャットの作品のような何のインターネット接続が(存在しないため、APIリクエストは多分エラーに遭遇したとき)、またはバックエンドにエラーがあった場合は、5秒後に再試行しますが、setTimeoutを1秒ごとに設定してストアの一部、つまり行this.props.decreaseTimeOut();を更新する必要がありますが、 5秒が経過したので、if blockは実行し、fetchData actionを再ディスパッチします。

少なくとも機能面では問題はありませんが、コードデザインの点ではside-effectであり、反応コンポーネントでは処理しないでください。私はredux-sagaを使用しています(しかし、私はredux-sagaを初めて使っています。私はそれを今日学んだだけです)。その機能を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

見えること素晴らしいですが、FETCH_DATA_STARTのtakeEveryを使用したくないのは、ユーザーが 'データをフェッチする 'ボタンを何度も何度も繰り返しクリックするだけで、複数のリクエストを送信することができ、私はそれを望んでいないので、私はテイクを使用したので、一度に1つ、それは悪いですか? –

+0

@ four-eyes-04-04あなたは必要なものを正確に実行する 'takeLatest'を使うことができます:) しかし、とにかく、あなたのコードは大丈夫ですが、私は' while true'構造が好きではありませんが、それはちょうど私が最初のスニペットで提案したように '遅延'を使用する – rpadovani

+0

あなたの提案をありがとう、私は正常に機能を実装することができた。 :-) –

関連する問題