【问题标题】:Axios request with chunked response stream from Node来自 Node 的带有分块响应流的 Axios 请求
【发布时间】:2020-03-16 14:55:11
【问题描述】:

我在 React 中有一个客户端应用程序,在 Node 中有一个服务器(使用 Express)。 在服务器端,我有一个类似以下的端点(不是真正的端点,只是我在做什么的一个想法):

function endpoint(req, res) {
   res.writeHead(200, {
        'Content-Type': 'text/plain',
        'Transfer-Encoding': 'chunked'
      });

   for(x < 1000){
      res.write(some_string + '\n');
      wait(a_couple_of_seconds); // just to make process slower for testing purposes
   }

   res.end();
}

这是完美的,我的意思是,当我调用这个端点时,我会收到包含所有 1.000 行的整个流。

问题是我无法设法按块获取这些数据(对于每个“写入”或一堆“写入”),以便在我收到它们后立即在前端显示..(想想在我从端点调用中获取行后立即显示行的表)

在前端,我使用 Axios 调用 API,代码如下:

async function getDataFromStream(_data): Promise<any> {
    const { data, headers } = await Axios({
        url: `http://the.api.url/endpoint`,
        method: 'GET',
        responseType: 'stream',
        timeout: 0,
    });

    // this next line doesn't work. it says that 'on' is not a function
    data.on('data', chunk => console.log('chunk', chunk)); 
    // data has actually the whole response data (all the rows)

    return Promise.resolve();
}

问题是 Axios 调用在调用服务器上的“res.end()”之后返回整个数据对象,但我需要在服务器开始发送带有行的块时立即获取数据(在每次 res.write 或服务器认为已准备好发送一些块时)。

我也尝试过不使用 await 并在 axios 调用的 'then()' 处获取 promise 的值,但这是相同的行为,'data' 值与所有 '一旦服务器执行 'res.end()'

那么,我在这里做错了什么?也许这对于 Axios 或 Node 是不可能的,我应该使用 websockets 之类的东西来解决它。 任何帮助都将不胜感激,因为我阅读了很多但还没有找到可行的解决方案。

【问题讨论】:

    标签: node.js reactjs axios


    【解决方案1】:

    对于任何对此感兴趣的人,我最终做的是以下内容:

    在客户端,我使用了允许处理下载进度事件的 Axios onDownloadProgress 处理程序。

    所以,我实现了这样的东西:

    function getDataFromStream(_data): Promise<any> {
        return Axios({
            url: `http://the.api.url/endpoint`,
            method: 'GET',
            onDownloadProgress: progressEvent => {
               const dataChunk = progressEvent.currentTarget.response;
               // dataChunk contains the data that have been obtained so far (the whole data so far).. 
               // So here we do whatever we want with this partial data.. 
               // In my case I'm storing that on a redux store that is used to 
               // render a table, so now, table rows are rendered as soon as 
               // they are obtained from the endpoint.
            }
    
    
        }).then(({ data }) => Promise.resolve(data));    
    
    }
    

    【讨论】:

    • dataChunk 包含到目前为止的所有块,因为我已经处理了以前的块,所以我只需要“新”块。有什么方法可以获取新的块?
    • 您是否可以控制服务器上的数据格式?如果是这样,您可以创建类似管道分隔的字符串,客户端可以解析该字符串以获取“最新”事件。下面是我如何解析看起来像 'event1|event2|event3|...' 的数据的示例: return axios.post('some/end/point', payload, { onDownloadProgress: (progressEvent) => { //RegEx获取 | 分隔字符串中的最后一项// const message = /\|([^|]+)\|$/.exec(progressEvent.currentTarget.response); EventBus.$emit('show-feedback', message ? 消息[1] : '', '成功'); } });
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2019-06-08
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多