使用 Event Source 实现服务端到客户端的单向推送,接收 text/event-stream 数据

1,070 阅读1分钟

在使用 eventSource 时发现,其只支持 GET 请求,如果我们接口是 POST,那么我们如何去实现它呢?

EventSource

EventSource 也称为 SSE(Server-Sent Events),是服务器推送的一个网络事件接口,一个 EventSource 会对 http 服务开启一个持久化链接,它发送的事件格式是text/stream,开启 EventSource 事件后,它会一直保持开启状态,直到达到某种条件后将其关闭。 具体使用如下

const eventSource = new EventSource('/sse');

eventSource.onopen = (event) => {
    console.log('连接成功');
};

eventSource.onmessage = (event) => {
    console.log('返回数据');
    if('达到关闭的条件') { 
        eventSource.close(); 
    }
};

eventSource.onerror = (error) => {
    console.log('eventSource error');
};

eventSource.onclose = (event) => {
    console.log('关闭连接成功');
};

其默认为 GET 方法,无法将其改为 POST,那我们怎么办呢?这时候就要使用插件去实现了。

使用插件实现 POST 的 eventSource 请求

安装插件 npm i --save @microsoft/fetch-event-source

import { fetchEventSource } from '@microsoft/fetch-event-source';

fetchEventSource(Url, {
    method: 'POST',
    headers: {
        "Content-Type": 'application/json',
    },
    body: JSON.stringify(data),
    onopen(event) {
      console.log('连接成功');
    },
    onmessage(event) {
       console.log('返回数据');
    },
    onclose() {
        // 数据返回结束时触发
        console.log('关闭连接成功');  
    },
    onerror() {
        console.log('eventSource error');
    }
})

这样就实现了使用 POST 请求 eventSource,不过使用这个插件还有个问题:当发送请求且暂未触发 onopen 事件前,离开当前窗口时会自动被取消,状态变为 canceled ,等再次切换回请求页面时会主动发起请求。(目前暂未寻到解决方案,各位大佬有啥解决方案可以多多留言)

通过 fetch 实现 接口返回的 text/event-stream 数据

const result = await fetch(`${url}`, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: {
        'Content-Type': 'application/json'
    },
})

const reader = result.body.getReader();
    while (true) {
    const { done, value } = await reader.read();
    if (done) {
        // 数据流已经处理完毕
        break;
    }
    // 将字节数据转换为文本
    const chunk = new TextDecoder('utf-8').decode(value);
    processLine(chunk);
}

const processLine = () => {
    // 处理数据
}