【问题标题】:onSnapshot() Firestore sending changes multiple times with Flask-SocketsonSnapshot() Firestore 使用 Flask-Sockets 多次发送更改
【发布时间】:2019-12-09 07:35:36
【问题描述】:

我正在尝试使用 Flask 和 Firestore 开发网络聊天。我设置了一个流程来接收来自 firestore 的新消息(当数据库发生变化时)并通过 websockets 发送到 UI。类似的东西:

Python:

@sockets.route('/messages')
def chat_socket(ws):
  message = None
  def callback_snapshot(col_snapshot, changes, read_time):
    with app.app_context():
      Messages = []
      for change in changes:
        if change.type.name == 'ADDED':
          Messages.append(change.document)
      conversation = render_template(
          'conversation.html',
          Messages = Messages,
        )
      numberID = None
      if len(col_snapshot) > 0:
        for i in col_snapshot:
          a = i 
        numberID = a.reference.parent.parent.id

      response = json.dumps({
        'conversation': conversation,
        'numberID': numberID
        })
      ws.send(response)

  while not ws.closed:

    response = json.loads(ws.receive())
    newNumberID = response['newNumberID'].strip()

    query_snapshot = fn.GetMessages(newNumberID)
    doc_watch = query_snapshot.on_snapshot(callback_snapshot)

    if message is None:
      continue

Javascript:

    function messages(numberID) {
  var scheme = window.location.protocol == "https:" ? 'wss://' : 'ws://';
  var webSocketUri =  scheme
    + window.location.hostname
    + (location.port ? ':'+location.port: '')
    + '/messages';

/* Get elements from the page */
  var form = $('#chat-form');
  var textarea = $('#chat-text');
  var output = $('.messages');
  var status = $('.messages');

  var websocket = new WebSocket(webSocketUri);

  websocket.onopen = function() {};

  websocket.onclose = function() {};

  websocket.onmessage = function(e) {    
    numberID = JSON.parse(e.data).numberID
    conversation = JSON.parse(e.data).conversation
    output.append(conversation);   
    if (numberID == null){
      output.empty();
    }};

  websocket.onerror = function(e) {console.log(e);};
  websocket.onopen = () => websocket.send(numberID);

};

问题是:当我使用 col_snapshot 作为消息时,除了每次发送消息时我都会将整个 firestore 集合发送给用户之外,一切都很好。所以它完全没有效率。如上所述,当我只为更改设置回调时,如果我多次触发该函数,不知何故我为同一个集合设置了多个侦听器,因此我在 UI 中获得了多个“更改更新”。如何跟踪这些听众,以便每个集合只设置一个听众?

【问题讨论】:

    标签: python flask websocket google-cloud-firestore flask-sockets


    【解决方案1】:

    正如您从documentation 中看到的那样,您应该对每个文档只调用一次GetMessageson_snapshot

    @sockets.route('/messages')
    def chat_socket(ws):
      message = None
      def callback_snapshot(col_snapshot, changes, read_time):
        with app.app_context():
          # Rest of the function ...
          ws.send(response)
    
      response = json.loads(ws.receive())
      numberID = response['newNumberID'].strip()
      query_snapshot = fn.GetMessages(numberID)
      doc_watch = query_snapshot.on_snapshot(callback_snapshot)
      while not ws.closed:
        newNumberID = response['newNumberID'].strip()
        response = json.loads(ws.receive())
        if newNumberID != numberID:
          numberID = newNumberID
          query_snapshot = fn.GetMessages(numberID)
          doc_watch = query_snapshot.on_snapshot(callback_snapshot)
    
    

    【讨论】:

    • 有道理,但是每次 newNumberID != numberID 时我如何取消订阅监听器?我的意思是,这将是对服务器的不同请求,所以我不能简单地使用 doc_watch.unsubscribe(),对吧?您发送的代码在我更改 numberID 时有效,但是当我使用相同的 numberID 多次通过时,我又遇到了问题(为同一个集合附加多个侦听器)。
    • 当您完成对文档的实时更新收听后,您应该分离监听器,以便您可以在该特定文档上附加一个新的监听器。 Here 是如何附加监听器,here 是如何分离它。
    猜你喜欢
    • 1970-01-01
    • 2018-10-02
    • 2021-01-14
    • 2020-03-21
    • 1970-01-01
    • 2020-09-02
    • 2021-03-14
    相关资源
    最近更新 更多