Angularjs SPA + Flask-Socketio活动多次被解雇

时间:2016-03-22 17:48:36

标签: python angularjs events flask socket.io

我在使用angularjs和socketio聊天应用时遇到的问题是,当向另一个用户发送消息时,显示消息的事件处理程序会被触发多次,因此屏幕上会出现多次相同的消息只希望它显示一次消息。有人可以解释为什么会发生这种情况以及如何解决这个问题。

这是我的客户端代码。我使用ngRoute来更改页面,而我正在使用服务来在切换页面时保留数据。

     // This method populates the chatbox on startup
     // Also it is emitted to on server side to display a new message
     socket.on("populateMessagesArchived", function (message) {
         $scope.tempArray = [message[0], message[1], message[2]];
         $scope.messages.push($scope.tempArray);
         $scope.$apply();
         $scope.tempArray = [];
         $scope.message="";
     });


     // When a users sends a message, this is invoked
     // this function gets the roomNum and message where roomNum corresponds to the roomNum where user sent message
     $scope.getMessage = function(roomNum, message) {
       $scope.tempArray = [roomNum, message, $scope.username];
       $scope.messages.push($scope.tempArray);
       socket.emit("storeMessagesInDatabase", {"uuid": $scope.uuid, "message": message, "roomNum": roomNum, "username": $scope.username});
       var element = document.getElementById('msgpane');
       element.scrollTop = element.scrollHeight;      
       $scope.tempArray = [];
       $scope.message="";
     };

服务器代码: 基本上将消息添加到postgresql数据库。并处理登录检查和注册。但我不认为这里存在问题。我注意到的是当我切换页面时,另一个socketio连接。 socketio连接的数量对应于打印出多少消息。但我不知道如何解决这个问题。任何帮助将不胜感激。

@socketio.on('userLoggedIn', namespace='/iss')
def loggedIn(user):        
    userData = user
    connect = connectToDB()
    cursor = connect.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cursor.execute("""select uuid, username from users WHERE username = %s AND password = crypt(%s, password);""", (userData['username'], userData['password']))
    #query1 = cursor.mogrify("""select * from users WHERE username = %s AND password = 'crypt(%s, password)';""", (userData['username'], userData['password']))
    query = cursor.fetchone()
    if query is not None:
        # Here we get the messages from the database and pass them to client side
        tempArray = retrieveMessagesFromDB()
        print tempArray
        emit('userAuthorized', query["uuid"], namespace='/iss')

        for message in tempArray:
            // emitted to client side to populate the chat room on login of a user
            emit("populateMessagesArchived", message, namespace='/iss')  
    else:
        emit('userNotAuthorized', namespace='/iss')

#
# retrieves the messages from the database to populate the chat rooms
#
def retrieveMessagesFromDB():
    connect = connectToDB()
    cursor = connect.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cursor.execute("""select messages.room_num, messages.message, users.username from users join messages on users.uuid = messages.uuid;""")
    query = cursor.fetchall()
    return query

#
# storeMessagesInDatabase - stores messages in the database
#
@socketio.on('storeMessagesInDatabase', namespace='/iss')
def storeMessagesInDatabase(userInfo):
    # userInfo is Json and we set it equal to tempDict
    tempDict=userInfo
    tempArray=[]
    tempArray.append(tempDict["roomNum"])
    tempArray.append(tempDict["message"])
    tempArray.append(tempDict["username"])
    connect = connectToDB()
    cursor = connect.cursor()

    try:
        cursor.execute("""insert into messages (uuid, message, room_num) values (%s, %s, %s);""", (str(tempDict["uuid"]), tempDict["message"], str(tempDict["roomNum"])))
    except:
        connect.rollback()
    connect.commit()   
    # Messages emitted back to client to be outputted on screen
    emit("populateMessagesArchived", tempArray, namespace='/iss', broadcast=True)
    tempArray=[]

1 个答案:

答案 0 :(得分:0)

我解决问题的方法是使用angular-socket-io库。它提供了一个forward()函数来阻止事件处理程序的重复,从而解决了重复消息的问题。此外,我现在理解MPA在页面切换和SPA上销毁套接字。我建议将socketio代码放在一个只调用一次的更高级别的模块中。有关更多说明,请参见此处:

  

https://stackoverflow.com/a/36223423/3103677