Javascript 在已经使用后重新分配变量?
我有一个我正在用React Native编写的应用程序。它是套接字的,我有一个控制所有套接字信息的文件Javascript 在已经使用后重新分配变量?,javascript,react-native,Javascript,React Native,我有一个我正在用React Native编写的应用程序。它是套接字的,我有一个控制所有套接字信息的文件 import {Alert, AppState} from 'react-native'; import store from '../store/store'; import {updateNotifications} from '../reducers/notifications'; import {setError, clearError} from '../reducers/error
import {Alert, AppState} from 'react-native';
import store from '../store/store';
import {updateNotifications} from '../reducers/notifications';
import {setError, clearError} from '../reducers/error';
import {updateCurrentEvent, updateEventStatus, setCurrentEvent} from '../reducers/event_details';
import {setAlert} from '../reducers/alert';
import {ws_url} from '../api/urls'
let conn = new WebSocket(ws_url);
/*
handleSocketConnections handles any actions that require rerouting. The rest are passed off to handleOnMessage
This is being called from authLogin on componentDidMount. It would be ideal to only initialize a socket conn
when a user logs in somehow, but this package gets ran when a user opens the app, meaning there are socket
connections that don't need to exist yet.
*/
function setAppStateHandler() {
AppState.addEventListener('change', cstate => {
if(cstate === 'active') {
reconnect()
}
})
}
export const handleSocketConnections = (navigator, route) => {
setAppStateHandler();
conn.onmessage = e => {
const state = store.getState();
const msg = JSON.parse(e.data);
const { type, payload, event_id } = msg;
const { event } = state.event_details.event_details;
if (type == "SET_EVENT_STATUS" && payload == "CLOSED" && event_id == event.event_id) {
navigator.push(route)
// store.dispatch(setAlert({
// message:"Event is closed, click to navigate to checkout."
// , scene: null
// }))
store.dispatch(updateEventStatus(payload));
} else {
handleOnMessage(msg, state)
}
}
}
export function reconnect() {
//TODO: Fatal errors should redirect the mainNav to a fatal error screen. Not dismount the nav entirely, as it does now
//and this should pop the error screen when it's fixed.
let state = store.getState();
conn = new WebSocket(ws_url);
setTimeout(function () {
if (conn.readyState == 1) {
if (typeof state.event_details.event_details != 'undefined') {
setSocketedEventInfo(state.event_details.event_details.event.event_id);
}
store.dispatch(clearError());
} else {
store.dispatch(setError('fatal',`Socket readyState should be 1 but it's ${conn.readyState}`))
}
}, 1000);
}
//Preform function on ES close.
conn.onclose = e => {
console.log("Closing wsbidder, ", `${e.code} -- ${e.reason}`);
//TODO: Set error here saying they need to restart the app. Maybe a 'reconnect' somehow?
//Maybe set a store variable to socketErr and if null, all is good. Else, panic the app?
//Use Case: Server is not started and user tries to connect to the app. String of e.message contains "Connection refused"
store.dispatch(setError("fatal", `Socket onclose: ${e.code} -- ${e.reason}`))
};
conn.onerror = e => {
console.log("Error at socket, ", e);
store.dispatch(setError("fatal", `Socket onerror: ${e.message}`))
};
//Initialization function for websocket.
// conn.onopen = e => console.log("Opening wsbidder, ", e)
function handleOnMessage(msg, state) {
switch (msg.type) {
//These types come from the SocketWrappers on the server.
//updateCurrentEvent should be filtering the event by event_id.
case "EVENT_ITEMS":
store.dispatch(updateCurrentEvent(
msg.payload
, state.user_info.uid
, state.event_details.event_details.event.event_id));
break;
case "NOTIFICATIONS":
//bug: this needs to filter notifications per event on the client-side.
store.dispatch(updateNotifications(
msg.payload
, state.event_details.event_details.event.event_id
, state.user_info.uid)
);
break;
case "NOT_BIDDABLE":
if (msg.event_id == state.event_details.event_details.event.event_id) {
store.dispatch(updateEventStatus("CLOSED"));
}
break;
case "PUSH_NOTIFICATION":
const {title, message} = msg.payload;
Alert.alert(title, message);
break;
default:
console.warn(`Unrecognized socket action type: ${msg.type}`);
}
}
//closes the socket connection and sends a reason to the server.
export const closeConn = reason => conn.close(null, reason);
export const setSocketedEventInfo = event_id => {
//Gives the event ID to the socketed connection, which pulls end dates.
const msg = {
type: "UPDATE_EVENT_DETAILS"
, payload: { event_id }
}
conn.send(JSON.stringify(msg));
}
export const createBid = (bid, cb) => {
/*
Expects:
const new_bid = {
item_id: item.item_id,
bid: amount, //Storage keeps storing it as a string
uid: 0, //Not needed here, but can't be null since the server wants an int.
event_id, key, bidder
};
*/
const new_bid = {
type: 'BID'
, payload: bid
};
// Send this to the server socket
conn.send(JSON.stringify(new_bid));
//Returning the callback so the front-end knows to flip the card back over.
return cb()
};
我知道有些代码是垃圾。除非你给出了真正的建议,我一直很乐意听从,否则没必要抨击它:-)
我遇到的问题是,当套接字死亡(conn变量)时,我无法重新初始化套接字并将其分配给该conn变量。我认为所有使用conn变量的函数都没有使用“新”变量,仍然使用“旧”变量
第9行--创建原始的
第28行——在handleSocketConnections函数中为conn对象创建onMessage函数,该函数在程序开始时在其他地方被调用
第57行--尝试在reconnect函数中为conn变量重新分配一个新连接,该函数在应用程序处于待机状态时运行(终止套接字连接)
第131行——通过重新连接函数正确调用它,再次将套接字连接到服务器
reconnect()函数运行正常-服务器使用所有正确的信息注册新连接,但应用程序似乎仍然处于一种奇怪的状态,没有连接错误(可能查看新连接???),但在连接上没有形成任何操作(可能查看旧连接?)
有什么想法吗?如果必须启动替换webSocket连接,则需要重新运行连接到webSocket的所有代码(安装事件处理程序等)。因为它是一个新对象,所以旧的事件侦听器与新的webSocket对象没有关联 最简单的方法通常是创建一个
webSocketInit()
函数,当您第一次创建webSocket连接时,可以调用这两个函数,然后在需要用新连接替换它时再次调用。您可以将最新的webSocket对象传递给webSocketInit()
,以便任何其他代码都可以看到新对象。如果单个代码块想知道旧代码块何时关闭,它们可以自己注册onclose
还有更多事件驱动的方法可以做到这一点,方法是创建一个EventEmitter,每当webSocket被替换时都会收到通知,如果单个代码块希望收到该事件的通知,则可以订阅该事件。您的代码确实应该发布在此处。更改了问题,添加了代码。您是对的,
onclose()
和onerror()
函数只绑定到最初创建的连接。每次创建新连接时,都必须重新分配这些。您可以通过将connection maker代码包装到自己的实用程序函数中来实现这一点。这会稍微澄清一些问题,但我正在尝试了解如何确保导出的连接使用新的连接对象。例如,“createBid”函数。@Nathanaland-您不需要使用webSocketInit()
函数来调用更新conn
变量createBid()
所使用的内容吗?