javascript - usar - Usando put dentro de devolución de llamada anónima
funciones anonimas javascript (1)
Estoy implementando Pusher en mi aplicación React + Redux Saga, pero estoy teniendo algunos problemas con algunas devoluciones de llamada en las que no puedo acceder a los métodos put(...)
. El uso de console.log(...)
etc. en los métodos se muestra, pero no puedo put
en el estado de mi aplicación.
Podría estar equivocado en algunas de las implementaciones de las funciones de asincronización / generador, pero estoy bastante atrapado en este momento.
Mi código para ilustrar lo que no se disparará:
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;
}
Solución basada en @Sebastien
yield put(yield onConnect(pusher));
function onConnect(pusher) {
return new Promise((resolve, reject) => {
pusher.connection.bind(''connected'', function() {
resolve(pusherConnectSucceeded(pusher));
});
});
}
Redux-saga no permite put
sin usar el yield
palabra clave. El put crea un objeto / efecto json simple que debe interpretarse / ejecutarse, y no lo hará si no cede.
Además, incluso con yield put(...)
, si esto se hace en una devolución de llamada, no se interpretará, porque Redux-saga no tiene la capacidad de ejecutar devoluciones de llamada en su intérprete. Simplemente se ejecutarán como devoluciones de llamada normales y no pasará nada.
Si se supone que subscription.bind
devuelve un solo resultado, en su lugar puede ajustar esa llamada a una función que devuelva una promesa y luego ceder esa promesa.
Si se supone que subscription.bind
devuelve una secuencia de resultados, es posible que lo necesite en lugar de crear un canal . Supongo que en el futuro alguien enviará algo que permita fácilmente transformar los Observables en secuencias de Redux-saga.
Tenga en cuenta que si no necesita darse de baja / volver a suscribir varias veces, puede ser más fácil para usted poner este código fuera de la saga, y simplemente haga
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));
}
});