Я пытаюсь подключиться с моего реагирующего приложения к websocket серверу, используя redux-saga и хочу перехватить потерю соединения (ошибка сервера, перезагрузка), чтобы восстановить соединение, скажем, с интервалами в 4 секунды, пока соединение снова не вернется.Проблема заключается в том, что при повторном подключении к webSocket redux store больше не обновляется.
Я пытался использовать eventChannel redux-saga, как показано в следующем коде.К сожалению, не было или, по крайней мере, я не смог найти никакой документации, отвечающей на wsconnect в redux-saga .
import {eventChannel} from 'redux-saga';
import {all, takeEvery, put, call, take, fork} from 'redux-saga/effects'
import {INITIALIZE_WS_CHANNEL} from "../../constants/ActionTypes"
import {updateMarketData} from "../actions"
function createEventChannel() {
return eventChannel(emit => {
//Subscribe to websocket
const ws = new WebSocket('ws://localhost:9000/rates');
ws.onopen = () => {
console.log("Opening Websocket");
};
ws.onerror = error => {
console.log("ERROR: ", error);
};
ws.onmessage = e => {
return emit({data: JSON.parse(e.data)})
};
ws.onclose = e => {
if (e.code === 1005) {
console.log("WebSocket: closed");
} else {
console.log('Socket is closed Unexpectedly. Reconnect will be attempted in 4 second.', e.reason);
setTimeout(() => {
createEventChannel();
}, 4000);
}
};
return () => {
console.log("Closing Websocket");
ws.close();
};
});
}
function * initializeWebSocketsChannel() {
const channel = yield call(createEventChannel);
while (true) {
const {data} = yield take(channel);
yield put(updateMarketData(data));
}
}
export function * initWebSocket() {
yield takeEvery(INITIALIZE_WS_CHANNEL, initializeWebSocketsChannel);
}
export default function* rootSaga() {
yield all ([
fork(initWebSocket)
]);
}
UPDATE
Чтобы завершить принятый ответ @azundo для того, кто ищет полный пример websocket & redux-saga, я добавляю следующий код:
function * initializeWebSocketsChannel() {
console.log("going to connect to WS")
const channel = yield call(createEventChannel);
while (true) {
const {data} = yield take(channel);
yield put(updateMarketData(data));
}
}
export function * startStopChannel() {
while (true) {
yield take(START_CHANNEL);
yield race({
task: call(initializeWebSocketsChannel),
cancel: take(STOP_CHANNEL),
});
//if cancel wins the race we can close socket
ws.close();
}
}
export default function* rootSaga() {
yield all ([
startStopChannel()
]);
}
START_CHANNEL и STOP_CHANNEL действия можно вызывать в componentDidMount и componentWillUnmount жизненного цикла реагирующего компонента, соответственно.