How can I use Axios with Server-sent events (SSE) in the browser?

打印 上一主题 下一主题

主题 1720|帖子 1720|积分 5160

题意:如何在浏览器中使用 Axios 处理服务器发送事故(SSE)?


题目背景:

I'm trying to receive Server-sent events (SSE) in the browser. My application uses axios (v1.6.8) to make API calls. This code works in node:
我正在实行在浏览器中接收服务器发送事故(SSE)。我的应用程序使用 axios(v1.6.8)举行 API 调用。以下代码可以在 Node.js 中运行:
  1. const getStreamAxios = () => {
  2.   axios.get('https://my-domain.com/api/getStream', {
  3.     responseType: 'stream',
  4.     headers: {
  5.       'Accept': 'text/event-stream',
  6.     }
  7.   })
  8.     .then(response => {
  9.       console.log('axios got a response');
  10.       const stream = response.data;
  11.       stream.on('data', data => {
  12.           console.log(data.toString('utf8'));
  13.       });
  14.       
  15.     })
  16.     .catch(e => {
  17.       console.error('got an error', e);
  18.     });   
  19. }
复制代码
But in the browser, the Promise is never fulfilled (i.e.: I don't get the console message "axios got a response"). Instead I get this warning in the console:
但是在浏览器中,Promise 永世不会被解决(即:我没有看到控制台信息 "axios got a response")。相反,我在控制台中收到了这个警告:
   The provided value 'stream' is not a valid enum value of type XMLHttpRequestResponseType.
  The issue is not in the API endpoint; in addition to checking it with node, I have verified it also works with Apidog and EventSource in the browser.
题目不在于 API 端点;除了使用 Node.js 举行查抄外,我还验证了它在 Apidog 和浏览器中的 `EventSource` 上也能正常工作。

题目解决:

The root of the problem is, axios as of v1.6.8, uses XMLHttpRequest in the browser (see axios docs). This means you can only use responseType: 'stream' in node.
题目的根源在于,axios 从 v1.6.8 开始在浏览器中使用的是 `XMLHttpRequest`(拜见 axios 文档)。这意味着你只能在 Node.js 中使用 `responseType: 'stream'`。

This was finally addressed in v1.7.0, which allows you to use fetch instead of XHR, like so:
这个题目最终在 v1.7.0 中得到了处理,该版本答应你使用 `fetch` 而不是 `XHR`,如下所示:
  1. const getStreamAxios = () => {
  2.   axios.get('https://my-domain.com/api/getStream', {
  3.     headers: {
  4.       'Accept': 'text/event-stream',
  5.     },
  6.     responseType: 'stream',
  7.     adapter: 'fetch', // <- this option can also be set in axios.create()
  8.   })
  9.     .then(async (response) => {
  10.       console.log('axios got a response');
  11.       const stream = response.data;      
  12.       // consume response
  13.       const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
  14.       while (true) {
  15.         const { value, done } = await reader.read();
  16.         if (done) break;
  17.         console.log(value);
  18.       }
  19.     })
  20.     // catch/etc.
  21. }
复制代码
If you are really invested in an older version of axios, there is a dodgy-looking workaround, using the onDownloadProgress option:
如果你非常依赖旧版本的 axios,可以使用一个看起来不太可靠的解决方法,纵然用 `onDownloadProgress` 选项:
  1. const getStreamAxios = () => {
  2.   axios.get('https://my-domain.com/api/getStream', {
  3.     headers: {
  4.       'Accept': 'text/event-stream',
  5.     },
  6.     onDownloadProgress: (evt) => {
  7.       // Parse response from evt.event.target.responseText || evt.event.target.response
  8.       // The target holds the accumulator + the current response, so basically everything from the beginning on each response
  9.       // Note that it's evt.target instead of evt.event.target for older axios versions
  10.       let data = evt.event.target.responseText;
  11.       console.log(data);
  12.     }
  13.   })
复制代码
Caveat
Note that, regardless of the option you choose, you will still have to write something to consume the server-sent events. Here's an example using @server-sent-stream/web:
请注意,无论你选择哪种方案,你仍然必要编写代码来处理服务器发送的事故。以下是一个使用 `@server-sent-stream/web` 的示例:
  1. const getStreamAxios = () => {
  2.   // axios.get(...) etc.
  3.   .then(async (response) => {
  4.     console.log('axios got a response');
  5.     const stream = response.data; // <- should be a ReadableStream
  6.     const decoder = new EventSourceStream();
  7.     stream.pipeThrough(decoder);
  8.     // Read from the EventSourceStream
  9.     const reader = decoder.readable.getReader();
  10.     while (true) {
  11.       const { value, done } = await reader.read();
  12.       if (done) break;
  13.       // The value will be a `MessageEvent`.
  14.       // MessageEvent {data: 'message data', lastEventId: '', …}
  15.       console.log(value)
  16.     }
  17.   })
  18. }
复制代码
If you don't want to parse this yourself, you can look at the native EventSource API. If you need more options not provided by EventSource (such as setting additional headers), you can take a look at options like sse.js, or this extended EventSource implementation
如果你不想自己解析这些事故,可以检察原生的 `EventSource` API。如果你必要 `EventSource` 未提供的更多选项(如设置额外的哀求头),可以考虑 `sse.js` 或这个扩展版的 `EventSource` 实现。




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表