2016-03-22 43 views
1

我正在使用angularjs和socketio聊天應用程序遇到的問題是,當向另一個用戶發送消息時,顯示消息的事件處理程序不止一次觸發,因此相同的消息不止一次出現在屏幕上,我只希望它顯示消息一次。有人可以解釋爲什麼會發生這種情況,以及如何解決這個問題。Angularjs SPA + Flask-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=[] 
+0

請[編輯]將這一數字減少到[MCVE。 – davidism

+0

@davidism更好嗎? – sebenalern

回答

0

我解決我的問題的方式是使用angular-socket-io庫。它提供了一個forward()函數來停止事件處理程序的重複,從而解決了重複消息的問題。現在,我明白MPA銷燬頁面切換套接字和SPA不會。我建議將socketio代碼放在只能調用一次的更高級別的模塊中。在這裏看到更多的解釋:

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