2016-06-09 43 views
10

Sto implementando Pusher nella mia applicazione React + Redux Saga, ma sto riscontrando alcuni problemi con alcuni callback in cui non riesco a trovare i metodi put(...). L'utilizzo di console.log(...) nei metodi mostra, ma non sono in grado di eseguire lo put nello stato della mia applicazione.Utilizzo della funzione di richiamo della funzione anonima

Potrei sbagliarmi su alcune delle implementazioni di funzioni asincrone/generatore, ma sono praticamente bloccato in questo momento.

Il mio codice per illustrare ciò che non sarà il fuoco:

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

// Pusher actions 
export const pusherConnecting =() => { 
    return { 
     type: ActionTypes.PUSHER_CONNECTING 
    } 
}; 

export const pusherConnectSucceeded = (client) => { 
    return { 
     type: ActionTypes.PUSHER_CONNECT_SUCCEEDED, 
     client: client 
    } 
}; 

const pusherConnectFailed = (exception) => { 
    return { 
     type: ActionTypes.PUSHER_CONNECT_FAILED, 
     message: exception 
    } 
}; 

// Pusher Saga 
function * connectPusher(action) { 
    try { 
     const pusher = yield call(Api.connectPusher, action.directory, function(subscription) { 
      subscription.bind(PUSHER_BIND_RELOAD, function() { 
       location.reload(true); 
      }); 

      subscription.bind(PUSHER_BIND_REQUEST_DATA, function(data) { 
       if (data) { 
        put(updateDirectory(data)); 
       } else { 
        put(requestDirectory(action.directory.id)); 
       } 
      }); 
     }); 

     pusher.connection.bind('connected', function() { 
      put(pusherConnectSucceeded(pusher)); 
     }); 

     yield put(pusherConnecting()); 

    } catch (e) { 
     yield put(pusherConnectFailed(e)); 
    } 
} 

export default function * pusherSaga() { 
    yield * takeLatest(ActionTypes.DIRECTORY_FETCH_SUCCEEDED, connectPusher); 
} 



// My Api.ConnectPusher 
export function * connectPusher(directory, subscription) { 
    var pusher = new Pusher(PUSHER_KEY, { 
     encrypted: true 
    }); 

    var channels = ["test1", "test2" ]; 

    for (var i = 0; i < channels.length; i++) { 
     // Take each channel and callback with the subscription 
     yield subscription(pusher.subscribe(channels[i])); 
    } 

    return pusher; 
} 

Soluzione basata su @Sebastien

yield put(yield onConnect(pusher)); 

function onConnect(pusher) { 
    return new Promise((resolve, reject) => { 
     pusher.connection.bind('connected', function() { 
      resolve(pusherConnectSucceeded(pusher)); 
     }); 
    }); 
} 
+0

Cosa significa "non viene colpito"? Non raggiungi quella linea? Come stai controllando, con un debugger? –

+0

Significa che non sono in grado di attivare questo metodo. Il metodo 'put'method non è invocato nel mio callback del metodo anonimo. O forse lo è, ma lo stato non sta cambiando (che è la mia mia domanda). – janhartmann

+0

Perché "forse"? Sembra che sarebbe una cosa ** veramente ** fondamentale da determinare, se "put" non viene raggiunto o raggiunto ma non ha l'effetto desiderato. Userei un debugger per seguire cosa, esattamente, succede, o (e questa è ** molto ** un'opzione di seconda classe) gettare alcuni 'console.log's. (Ma rispetto al girare con una torcia 'console.log', usare un debugger è come accendere le luci.) –

risposta

6

Redux-saga non permette di put senza l'utilizzo di parole chiave yield. Il put crea un semplice oggetto/effetto json che deve essere interpretato/eseguito, e non lo farà se non cedi.

Inoltre, anche con yield put(...), se questo viene eseguito in un callback, non verrà interpretato, perché Redux-saga non ha la possibilità di eseguire callback nel suo interprete. Saranno semplicemente eseguiti come normali callback e non succederà nulla.

Se subscription.bind deve restituire un risultato singolo, è possibile invece avvolgere quella chiamata in una funzione che restituisce una promessa e quindi produrre tale promessa.

Se subscription.bind restituisce un flusso di risultati, potrebbe essere necessario invece di creare un channel. Immagino che in futuro qualcuno spedirà qualcosa che può facilmente permettere di trasformare gli osservabili in stream di Redux-saga

Si noti che se non è necessario annullare l'iscrizione/riscrivere più volte, potrebbe essere più semplice per voi inserire questo codice al di fuori della saga, e basta fare

 subscription.bind(PUSHER_BIND_RELOAD, function() { 
      location.reload(true); 
     }); 

     subscription.bind(PUSHER_BIND_REQUEST_DATA, function(data) { 
      if (data) { 
       reduxStore.dispatch(updateDirectory(data)); 
      } else { 
       reduxStore.dispatch((requestDirectory(action.directory.id)); 
      } 
     }); 
+0

** QUESTO ** è quello che dovevo sapere. Elaborerò una soluzione e aggiornerò la mia risposta con una soluzione. Molte grazie! – janhartmann

+0

puoi fornire un semplice esempio su "Se subscription.bind dovrebbe restituire un singolo risultato, puoi invece racchiudere quella chiamata in una funzione che restituisce una promessa, e quindi produrre quella promessa"? – janhartmann

+0

Aggiornato la mia domanda con la mia soluzione, pensi che sia abbastanza buono? – janhartmann