2017-05-08 5 views
1

in meiner Anwendung habe ich den folgenden CodeWiederholungs Funktionalität in redux-Saga

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); 
    } 
} 

Was sie tut, ist, dass, wenn eine API-Anforderung vielleicht ein Fehler aufgetreten ist, weil es keine Internet-Verbindung (wie, wie Facebook-Chat-Werke), oder es gab einen Fehler im Backend, es würde nach fünf Sekunden wiederholt, aber der setTimeout muss jede Sekunde gesetzt werden, um einen Teil des Speichers zu aktualisieren, dh die Zeile this.props.decreaseTimeOut();, aber wenn der Zähler abgelaufen ist aus, also sind fünf Sekunden vergangen, die if block würde laufen und die fetchData action erneut versenden.

Es funktioniert gut und ich habe kein Problem damit, zumindest in Bezug auf Funktionalität, aber in Bezug auf Code-Design, weiß ich, dass es ein side-effect ist und es sollte nicht in meiner Reaktionskomponente behandelt werden, und seit ich verwende redux-saga (aber ich bin neu bei redux-saga, ich habe es gerade erst gelernt), ich möchte diese Funktionalität in eine Saga umwandeln, ich habe noch keine Idee, wie ich das noch machen soll, und hier ist meine fetchData saga übrigens.

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 }); 
    } 
    } 
} 

Antwort

2

Je weniger aufdringlich, was für Ihren Code der delay Versprechen von redux-Saga mit:

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/*); 
    } 
} 

Aber ich Ihren Code auf diese Weise umgestalten würde:

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

Das sieht genial, aber ich möchte TakeEvery nicht für meine FETCH_DATA_START verwenden, weil das den Benutzern erlauben würde, einfach auf die 'Daten holen'-Schaltfläche zu klicken und immer wieder mehrere Anfragen zu senden, und das möchte ich nicht, ich möchte nur Reques senden t einer nach dem anderen, also habe ich gebraucht, ist das schlimm? –

+0

@ four-eyes-04-04 dann können Sie 'takeLatest' verwenden, das genau das tut, was Sie brauchen :) Aber egal, Ihr Code ist in Ordnung, ich mag einfach nicht die' while true' Struktur, aber wenn Sie bevorzugen Verwenden Sie einfach die 'Verzögerung', wie ich im ersten Snippet vorgeschlagen habe – rpadovani

+0

Vielen Dank für Ihren Vorschlag, ich konnte das Feature erfolgreich implementieren. :-) –

Verwandte Themen