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