使用WebSocket时发生意外行为

问题描述

我想创建一个基本的聊天系统,允许用户file附加到给定的消息上。

web sockets存在问题,因为通过它们发送file非常困难。除非您要将其转换为二进制数据。但是,这对我不起作用,因为我希望能够与服务器上的文件进行交互,并且由于我具有多种文件类型(不同的图像,视频和gif图像),所以我不能只解码二进制文件

这是我的代码

我在request上传邮件的位置:

// this.state._new_message : {
//     _message_type_id:int,//     _message:string || file,//     _user_id:int,//     _conversation_id:int
// } -> this is what a _new_message object looks like.

let fd = new FormData()

if(this.state._new_message._message_type_id !== 1){
    fd.append("file",this.state._new_message._message)
}

fd.append("message",JSON.stringify(this.state._new_message))

Axios.post(API_URL+"/api/chat/send_message",fd)
.then(res => res.data)
.then(res => {
    this.socket.emit("message",res._message)
})

我处理request的地方:

def send_message(self,request):
    data = request.form["message"]
    data = json.loads(data)
    if data["_message_type_id"] != 1:
        data["_message"] = "Loading Message. Please Wait."

    query = fdb.prepare(data,"_messages") # Converts the data dict to a query string

    fdb.create(query["query_string"],query["query_params"]) # Interacts with Database
    _message = fdb.read("""SELECT * FROM _messages WHERE _id = LAST_INSERT_ID()""",(),False)

    if data["_message_type_id"] != 1:
        file = request.files["file"]
        # OpenCV magic... #
        path = "path/to/file"
        file.save(path)
            
        fdb.update("""UPDATE _messages SET _message = %s WHERE _id = %s""",(url_path,_message["_id"])) # Interacts with Database
        url_path = "url/path/to/file"
        _message["_message"] = url_path # If message is not text,set it to be the path to the file instead
        
        
    return jsonify({
        "_message" : _message
    })

这是我收听eventserver)的地方:

@socket.on("message")
def handleMessage(msg):
    print(msg)
    send(msg,broadcast=True)
    return None

这是我收听eventclient)的地方:

this.socket.on("message",data => {
    if(data == null || data._message_type_id == undefined) return
    if(this.props.chat.messages.messages !== null)
        if(this.props.chat.messages.messages.filter(message => parseInt(message._id) === parseInt(data._id)).length > 0) return
    this.props.addMessage(data)
})

根据该代码,您希望通过HTTP发送一条消息,该消息将通过HTTP处理并发送回去,然后将响应发送到server通过socketsocket,然后将该send消息发送给所有正在监听该clients的{​​{1}}。但这不是那样的。有时候会,有时候却没有。

我可以确认的一件事是,消息会100%地保存到数据库文件系统中。我也总是收到socket的响应,但是当我在服务器中从HTTP requestemit收到event client消息时,我有时得到print或上一条消息记录到控制台。

因此,当该消息发送到None时,我的“ client”将看到其error catching block或已经存在,因此它将undefined而不添加它(因为它当然不应该添加)。

有人曾经遇到过这个问题吗?我对某事有错误的主意吗?还是我的代码有问题?

解决方法

我知道了。

经过一段时间的分析,我发现我不在同一executequeries后面的两个transaction

fdb.create(query["query_string"],query["query_params"]) # Interacts with Database
_message = fdb.read("""SELECT * FROM _messages WHERE _id = LAST_INSERT_ID()""",(),False)

我开发的fdb扩展基本上是sqlalchemy的高级抽象,它具有非常宽松的事务管理系统(自动打开/关闭)。因此,我不得不隐式告诉它在执行两个查询之前不要关闭事务。

结果,我总是得到最新的插入内容,而不是事先发生的插入内容(就像我更新代码之前的情况一样)。

向您展示,如果您不考虑所有高级用例,那么抽象代码并不总是一个好主意。