Чтение потокового ответа по мере поступления - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь запустить долгосрочную (10-30 секунд) работу на нашем сервере и следить за ее ходом без закрытия соединения. По сути, я загружаю файл и передаю прогресс обратно клиенту, разделенному символами новой строки. Вот пример ответа (каждая новая строка задерживается на пару миллисекунд):

01
23
48
60
73
87
96

Я смог заставить это работать, используя экспериментальные ReadableStream и TextDecoder apis, но я ищу более совместимый с браузером способ. Вот мой код:

fetch('/thing/').then(r => {
  let reader = r.body.getReader('byob')

  const doIt = () => {
    reader.read().then(({done, value}) => {
      value = new TextDecoder("utf-8").decode(value)

      if (done) {
        clearInterval(interval)
      }

      if (value) {
        console.log(`${value}% done`)
      }
    })
  }

  const interval = setInterval(doIt, 10)
})

Я пытался установить responseType для XMLHttpRequest равным blob и arraybuffer, проверяя ответ каждую миллисекунду, но не смог получить ни один из них для потоковой передачи; он просто распечатал бы полный ответ по окончании.

1 Ответ

0 голосов
/ 15 сентября 2018

Вот решение, которое я придумал:

function monitorServerSentEvents(url, opts, onProgress) {
  const headers = {'Content-Type': false, 'Accept': false}

  return fetch(url, {headers, ...opts}).then(res => {
    const reader = res.body.getReader('byob')

    return new Promise((resolve, reject) => {
      ;(function readProgress() {
        reader.read()
          .catch(reject)
          .then(({done, value}) => {
            if (done) {
              resolve()
            }

            if (!value) {
              return
            }

            const decoder = (new TextDecoder("utf-8"))
            const progress = decoder.decode(value).trim().split('\n')

            progress.forEach(onProgress)

            setTimeout(readProgress, 50)
          })
      }())
    })
  })
}

Это работает только в браузере, который поддерживает ReadableStream.getReader .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...