读取流式响应

问题描述 投票:0回答:1

我正在尝试在我们的服务器上启动一个长时间运行(10-30秒)的作业,并在不关闭连接的情况下监视它的进度。基本上,我上传了一个文件,并将进度传递回由换行符分隔的客户端。这是一个示例响应(每个换行延迟几毫秒):

01
23
48
60
73
87
96

我能够使用实验性的ReadableStreamTextDecoder 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)
})

我已经尝试将XMLHttpRequest上的responseType设置为blobarraybuffer,每隔毫秒检查一次响应,但无法获得流式传输;它会在完成后打印出完整的响应。

javascript browser stream xmlhttprequest
1个回答
0
投票

这是我提出的解决方案:

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的浏览器。

© www.soinside.com 2019 - 2024. All rights reserved.