簡體   English   中英

使用 websockets 時的意外行為

[英]Unexpected behavior when using websockets

我想創建一個基本的聊天系統,允許用戶將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該消息給所有的正在偵聽該socket clients 但它不是那樣工作的。 有時會,有時不會。

我可以確認的一件事是,消息 100% 的時間都保存到數據庫和文件系統中。 我也總是從HTTP request得到響應,但是當我從client emit event並在服務器中print消息時,有時我會得到None或之前的消息記錄到控制台。

因此,當該消息發送到client ,我的“ error catching block ”將看到它undefined或已存在,因此它將return而不添加它(因為它當然不應該添加它)。

有沒有人遇到過這個問題? 我對某事有錯誤的看法嗎? 還是我的代碼有問題?

我想到了。

經過一段時間分析我的代碼后,我注意到我沒有在同一個transaction execute以下兩個queries

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高級抽象,它具有非常松散的事務管理系統(自動打開/關閉)。 所以我不得不隱含地告訴它在執行兩個查詢之前不要關閉事務。

結果,我總是得到最新的插入,而不是事先發生的插入(就像我更新代碼之前的情況一樣)。

向您展示,如果您沒有提前考慮所有用例,代碼抽象並不總是一個好主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM