在 Redux Saga 中重用 websocket 连接对象
Reusing websocket connection object in Redux Saga
我有问题。我在 React Redux eventChannel 内的 websocket 的帮助下连接到服务器。我从服务器接收事件没有问题,但我无法将事件发送到服务器。我知道,我需要获取我在 eventChannel 中创建的 websocket 连接对象,例如从 React 组件发送事件。
export function* wsWatcher() {
yield takeEvery("LOGIN_SUCCESS", wsConnectionWorker);
}
function* wsConnectionWorker() {
const channel: EventChannel<boolean> = yield call(initWebsocket);
while (true) {
const action: Action<any> = yield take(channel);
yield put(action);
}
}
function initWebsocket(): EventChannel<any> {
return eventChannel((emitter) => {
let id: string | undefined;
let intervalId: number;
const initConnection = () => {
const connectionUrl: string = "ws://localhost:4000"
let ws = new WebSocket(connectionUrl);
ws.onopen = () => {
id && ws.send(JSON.stringify({ type: "GET_USER_ID", id }));
intervalId = window.setInterval(() => {
ws.send(JSON.stringify({ type: "PING" }))
}, 30000)
};
ws.onclose = (e) => {
console.log("Reconnect in 4s");
intervalId && clearInterval(intervalId);
id && setTimeout(initConnection, 4000);
};
};
initConnection();
return () => {
console.log("Socket off");
};
});
}
提前致谢
您可以在模块的范围内创建一个变量,并在第一次初始化后将连接对象存储在其中。以后需要连接时,只需使用此变量即可。
这是有效的,因为模块缓存在 nodejs 中。也就是说,运行 中模块中的代码仅在首次导入时使用,之后的导入使用缓存的模块。
如需进一步参考,请阅读更多内容:Modules Caching
您也可以为此设置一个函数,例如此代码中的 getConnection
函数。每当您需要 websocket 连接时,调用此函数,它只会创建一次连接。
export function* wsWatcher() {
yield takeEvery("LOGIN_SUCCESS", wsConnectionWorker);
}
function* wsConnectionWorker() {
const channel: EventChannel<boolean> = yield call(getConnection);
while (true) {
const action: Action<any> = yield take(channel);
yield put(action);
}
}
// store the EventChannel after first init
let wsConnection: EventChannel<any> = null;
// create WS connection on first call
// reuse that connection in further calls
function getConnection(): EventChannel<any>{
if(!wsConnection){
wsConnection = initWebsocket();
return wsConnection;
}
function initWebsocket(): EventChannel<any> {
return eventChannel((emitter) => {
let id: string | undefined;
let intervalId: number;
const initConnection = () => {
const connectionUrl: string = "ws://localhost:4000"
let ws = new WebSocket(connectionUrl);
ws.onopen = () => {
id && ws.send(JSON.stringify({ type: "GET_USER_ID", id }));
intervalId = window.setInterval(() => {
ws.send(JSON.stringify({ type: "PING" }))
}, 30000)
};
ws.onclose = (e) => {
console.log("Reconnect in 4s");
intervalId && clearInterval(intervalId);
id && setTimeout(initConnection, 4000);
};
};
initConnection();
return () => {
console.log("Socket off");
};
});
}
我有问题。我在 React Redux eventChannel 内的 websocket 的帮助下连接到服务器。我从服务器接收事件没有问题,但我无法将事件发送到服务器。我知道,我需要获取我在 eventChannel 中创建的 websocket 连接对象,例如从 React 组件发送事件。
export function* wsWatcher() {
yield takeEvery("LOGIN_SUCCESS", wsConnectionWorker);
}
function* wsConnectionWorker() {
const channel: EventChannel<boolean> = yield call(initWebsocket);
while (true) {
const action: Action<any> = yield take(channel);
yield put(action);
}
}
function initWebsocket(): EventChannel<any> {
return eventChannel((emitter) => {
let id: string | undefined;
let intervalId: number;
const initConnection = () => {
const connectionUrl: string = "ws://localhost:4000"
let ws = new WebSocket(connectionUrl);
ws.onopen = () => {
id && ws.send(JSON.stringify({ type: "GET_USER_ID", id }));
intervalId = window.setInterval(() => {
ws.send(JSON.stringify({ type: "PING" }))
}, 30000)
};
ws.onclose = (e) => {
console.log("Reconnect in 4s");
intervalId && clearInterval(intervalId);
id && setTimeout(initConnection, 4000);
};
};
initConnection();
return () => {
console.log("Socket off");
};
});
}
提前致谢
您可以在模块的范围内创建一个变量,并在第一次初始化后将连接对象存储在其中。以后需要连接时,只需使用此变量即可。
这是有效的,因为模块缓存在 nodejs 中。也就是说,运行 中模块中的代码仅在首次导入时使用,之后的导入使用缓存的模块。
如需进一步参考,请阅读更多内容:Modules Caching
您也可以为此设置一个函数,例如此代码中的 getConnection
函数。每当您需要 websocket 连接时,调用此函数,它只会创建一次连接。
export function* wsWatcher() {
yield takeEvery("LOGIN_SUCCESS", wsConnectionWorker);
}
function* wsConnectionWorker() {
const channel: EventChannel<boolean> = yield call(getConnection);
while (true) {
const action: Action<any> = yield take(channel);
yield put(action);
}
}
// store the EventChannel after first init
let wsConnection: EventChannel<any> = null;
// create WS connection on first call
// reuse that connection in further calls
function getConnection(): EventChannel<any>{
if(!wsConnection){
wsConnection = initWebsocket();
return wsConnection;
}
function initWebsocket(): EventChannel<any> {
return eventChannel((emitter) => {
let id: string | undefined;
let intervalId: number;
const initConnection = () => {
const connectionUrl: string = "ws://localhost:4000"
let ws = new WebSocket(connectionUrl);
ws.onopen = () => {
id && ws.send(JSON.stringify({ type: "GET_USER_ID", id }));
intervalId = window.setInterval(() => {
ws.send(JSON.stringify({ type: "PING" }))
}, 30000)
};
ws.onclose = (e) => {
console.log("Reconnect in 4s");
intervalId && clearInterval(intervalId);
id && setTimeout(initConnection, 4000);
};
};
initConnection();
return () => {
console.log("Socket off");
};
});
}