Источник событий React не закрыт

#javascript #reactjs #server-sent-events

#javascript #reactjs #отправленные сервером события

Вопрос:

Я новичок в веб-разработке и, в частности, в отправленных сервером событиях, поэтому, вероятно, я упускаю что-то очевидное. Я пытаюсь отобразить регистратор на странице реакции с помощью отправленных сервером событий, который работает нормально, но я не могу закрыть EventSource. Сервер непрерывно получает запросы после вызова EventSource.close() .

   const [eventSource, setEventSource] = React.useState(new EventSource("http://localhost:5001/logs"))
  const [logs, setLogs] = React.useState([])

  React.useEffect(() => {
    eventSource.onmessage = e => updateLogs((e.data))

    return (() => eventSource.close() )
  }, [])

  const updateLogs = (entry) => {
    setLogs(logs => [...logs, entry])
    if (entry === 'finished'){
      eventSource.close()
      console.log('closed eventsource')
      setEventSource(null)
    }
  }
  

Консоль регистрирует «закрытый eventsource», как и ожидалось, и перехват журналов больше не обновляется, но запросы продолжают откуда-то запускаться. Чего мне не хватает?

Запросы обрабатываются сервером flask следующим образом (просто отправьте несколько фиктивных журналов):

 def log_progress():
  for i in range(10):
    message = 'data: step {} nn'.format(i)
    yield message
    time.sleep(1)
  yield 'data: finishednn'

@app.route("/logs")
def stream_logs():
    return = Response(log_progress(), mimetype="text/event-stream")
  

Журнал сервера:

 <Response streamed [200 OK]>
127.0.0.1 - - [02/Oct/2020 11:00:22] "GET /logs HTTP/1.1" 200 -
<Response streamed [200 OK]>
127.0.0.1 - - [02/Oct/2020 11:00:22] "GET /logs HTTP/1.1" 200 -
<Response streamed [200 OK]>
127.0.0.1 - - [02/Oct/2020 11:00:22] "GET /logs HTTP/1.1" 200 -
<Response streamed [200 OK]>
127.0.0.1 - - [02/Oct/2020 11:00:23] "GET /logs HTTP/1.1" 200 -
<Response streamed [200 OK]>
127.0.0.1 - - [02/Oct/2020 11:00:23] "GET /logs HTTP/1.1" 200 -
// this keeps on forever until page is closed
  

Ответ №1:

Наконец, я нашел обходной путь (я до сих пор не понимаю, почему первоначальный подход не сработал). Вместо того, чтобы использовать перехват для хранения EventListener, я обработал все в перехвате useEffect, который вызывается при монтировании с помощью addEventListener():

   React.useEffect(() => {
    let eventSource = new EventSource("http://localhost:5001/logs")
    // eventSource.onmessage = event => updateLogs((event.data))
    eventSource.addEventListener('newEntry', e =>
      updateLogs(e.data)
    )
    eventSource.addEventListener('close', () =>
      eventSource.close()
    )

    return (() => eventSource.close() )
  }, [])
  

И на сервере я добавил типы событий:

 def log_progress():
  for i in range(10):
    message = 'event: newEntryn'
    message  = 'data: step {} nn'.format(i)
    yield message
    time.sleep(1)
  yield 'event: closendata: finished nn'
@app.route("/logs")
def stream_logs():
    return = Response(log_progress(), mimetype="text/event-stream")