2016-06-09 16 views
10

Ich bin Pusher in meine React + Redux Saga-Anwendung implementieren, aber ich habe ein paar Probleme mit einigen Callbacks, wo ich die put(...) Methoden nicht treffen kann. Using console.log(...) etc. in den Methoden zeigt, aber ich bin nicht in der Lage, put auf den Stand meiner Anwendung.Verwendung innerhalb anonymer Funktion Callback

Ich könnte falsch bei einigen der Implementierung von Async/Generator-Funktionen, aber ich bin ziemlich genau jetzt stecken.

Mein Code zu veranschaulichen, was nicht Feuer:

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

Lösung auf Basis von @Sebastien

yield put(yield onConnect(pusher)); 

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

Was bedeutet "nicht getroffen" bedeutet? Du erreichst diese Linie nicht? Wie überprüfen Sie mit einem Debugger? –

+0

Es bedeutet, dass ich diese Methode nicht auslösen kann. Die Put-Methode wird in meinem anonymen Methoden-Callback nicht aufgerufen. Oder vielleicht ist es so, aber der Staat ändert sich nicht (was meine Frage ist). – janhartmann

+0

Warum "vielleicht"? Es scheint so zu sein, als wäre es eine wirklich grundlegende Frage, ob "Put" nicht erreicht wird oder erreicht wird, aber nicht den gewünschten Effekt hat. Ich würde einen Debugger verwenden, um zu verfolgen, was genau passiert, oder (und das ist ** sehr ** eine Option der zweiten Klasse), werfen Sie einige 'console.log's ein. (Aber im Vergleich mit einem "console.log" Fackel herumwandern, ist die Verwendung eines Debuggers wie das Einschalten der Lichter.) –

Antwort

6

Redux-Saga ermöglicht nicht zu put ohne Schlüsselwort yield zu verwenden. Der Put erstellt ein einfaches Json-Objekt/einen JSON-Effekt, der interpretiert/ausgeführt werden muss, und nicht, wenn Sie nicht nachgeben.

Auch bei yield put(...), wenn dies in einem Callback durchgeführt wird, wird es nicht interpretiert, da Redux-Saga keine Callbacks in seinem Interpreter ausführen kann. Sie werden einfach als normale Rückrufe ausgeführt und nichts wird passieren.

Wenn subscription.bind ein einzelnes Ergebnis zurückgeben soll, können Sie diesen Aufruf stattdessen in eine Funktion umwandeln, die eine Zusage zurückgibt und dann diese Zusage liefert.

Wenn subscription.bind einen Strom von Ergebnissen zurückgeben soll, müssen Sie möglicherweise einen channel erstellen. Ich schätze, in der Zukunft wird jemand etwas versenden, das leicht erlaubt, Observables zu Redux-Saga Streams

zu verwandeln. Beachten Sie, dass wenn Sie nicht mehrmals abbestellen/neu abonnieren müssen, es einfacher für Sie sein kann, diesen Code zu setzen Außerhalb der Saga, und tun Sie einfach

 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

** DIESES ** ist, was ich wissen musste. Ich werde eine Lösung erarbeiten und meine Antwort mit einer Lösung aktualisieren. Danke vielmals! – janhartmann

+0

können Sie ein einfaches Beispiel für die "Wenn subscription.bind ein einzelnes Ergebnis zurückgeben soll, können Sie stattdessen diesen Aufruf in eine Funktion, die eine Zusage zurückgibt und dann diese Versprechen geben"? – janhartmann

+0

Aktualisiert meine Frage mit meiner Lösung, denken Sie, das ist gut genug? – janhartmann

Verwandte Themen