在使用之后重新分配变量?

时间:2016-07-13 23:29:02

标签: 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 {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变量的所有函数都没有使用' new'一个,仍然坚持“老”'之一。

第9行 - 创建原始文件。

第28行 - 在handleSocketConnections函数中为conn对象创建onMessage函数,该函数在程序开头的其他位置调用

第57行 - 尝试重新为重新连接函数中的conn变量分配新连接,该连接在应用程序进入待机状态时运行(终止套接字连接)。

第131行 - 从重新连接功能正确调用它,再次将套接字连接到服务器

reconnect()函数正确运行 - 服务器使用所有正确的信息注册新连接,但应用程序似乎仍然处于一种奇怪的状态,其中没有conn错误(可能正在查看新的错误) ??)但是没有在conn上形成任何动作(可能会看到旧的?)。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

如果必须启动替换webSocket连接,则需要重新运行连接到webSocket的所有代码(安装事件处理程序等等)。因为它是一个新对象,旧的事件监听器与新的webSocket对象没有关联。

最简单的方法通常是创建一个webSocketInit()函数,在第一次创建webSocket连接时调用该函数,然后在必须用新的函数替换它时再次调用。您可以将最新的webSocket对象传递给webSocketInit(),以便任何其他代码都可以看到新对象。如果个别代码块想知道旧代码何时关闭,则可以自行注册代码。

还有更多事件驱动的方法可以通过创建一个EventEmitter来实现这一点,只要webSocket被替换就会收到通知,并且如果他们希望得到该事件的通知,则各个代码块可以订阅该事件。