onSnapshot()Firestore使用Flask-Sockets多次发送更改

时间:2019-12-09 07:35:36

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

我正在尝试与Flask和Firestore建立网络聊天。我设置了一个流程,以从Firestore接收新消息(当数据库发生更改时),并通过websocket发送到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中会获得多个“更改更新”。如何跟踪那些听众,以便每个收藏集只设置一个听众?

1 个答案:

答案 0 :(得分:0)

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)