gpt4 book ai didi

reactjs - 在 redux-Saga 中重新连接到 webSocket 服务器的标准方法?

转载 作者:行者123 更新时间:2023-12-04 15:40:18 32 4
gpt4 key购买 nike

我正在尝试使用 redux-saga 从我的 react App 连接到 websocket 服务器,并希望捕获连接丢失(服务器错误,重新启动)以便以 4 秒的间隔重新连接,直到连接再次恢复。问题是在重新连接到 webSocket 时 redux store 不再更新。

我尝试按照以下代码使用 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_CHANNELSTOP_CHANNEL 操作可以在 componentDidMountcomponentWillUnmount 分别是 React 组件生命周期。

最佳答案

这不起作用的原因是因为您对 createEventChannel 的递归调用没有被 yielded 到 saga 中间件 redux-saga无法知道后续事件 channel 的创建。您会希望在事件 channel 中定义递归函数,请参阅下面的代码,因此只有一个 eventChannel 始终挂接到商店中。

另请注意,在预期的套接字关闭时添加了发射 END,这样您就不会在不重新连接时让 eventChannel 永远打开。

import {eventChannel, END} from 'redux-saga';

let ws; //define it here so it's available in return function

function createEventChannel() {
return eventChannel(emit => {
function createWs() {
//Subscribe to websocket
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");
// you probably want to end the channel in this case
emit(END);
} else {
console.log('Socket is closed Unexpectedly. Reconnect will be attempted in 4 second.', e.reason);
setTimeout(() => {
createWs();
}, 4000);
}
};
}
createWs();

return () => {
console.log("Closing Websocket");
ws.close();
};
});
}

关于reactjs - 在 redux-Saga 中重新连接到 webSocket 服务器的标准方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58026629/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com