【发布时间】:2020-01-21 09:50:16
【问题描述】:
我正在尝试使用 redux-saga 从我的 react App 连接到 websocket 服务器并希望捕获连接丢失(服务器错误,重新启动),以便每隔 4 秒重新连接一次,直到连接再次恢复。问题在于重新连接到 webSocket,redux 存储不再更新。
我尝试按照以下代码使用 redux-saga 的 eventChannel。不幸的是,没有或至少我找不到任何文档回答 ws reconnect in 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)
]);
}
更新
为了完成@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 分别是 react 组件的生命周期。
【问题讨论】:
-
我看到了你的回答,使用 componentDidMount 和 componentWillUnmount 听起来是个好主意,但是如果我们在 componentDidMount 上断开连接,一段时间后我们想再次连接怎么办?
标签: reactjs redux websocket redux-saga