Egg + SSE

1,609 阅读1分钟

无插件版

router.js

router.get('/event-test', controller.index.event);

controller/index.js

'use strict';
const Controller = require('egg').Controller;

class BaseController extends Controller {
  async event() {
    const stream = new PassThrough();

    this.ctx.set('Content-Type', 'text/event-stream');
    this.ctx.set('Connection', 'keep-alive');
    this.ctx.set('Cache-Control', 'no-cache');
    this.ctx.set('Access-Control-Allow-Origin', '*');

    const timer = setInterval(() => {
      stream.write('event:eventName\nretry:1000\nid:1\ndata: hello\n\n');
    }, 1000);
    
    stream.on('close', function() {
      console.log('closed.');
      clearInterval(timer);
    });

    this.ctx.body = stream;
  }
}
}

module.exports = BaseController;

浏览器:

const event = new EventSource('http://{host}/event-test');
event.addEventListener('open', e => {
  console.log('open:', e);
});
event.addEventListener('message', e => {
  console.log('get event:', e);
});
event.addEventListener('error', e => {
  console.log('has error:', e);
  event.close();
});
// 浏览器接受到的消息中含id时,会在本地存last-event-id,在发起重连的请求中会放到reques head中

使用egg-sse

注意:

  1. 使用本地自定义的非localhost域名时会出现 eventsource 一直pending
  2. 发送的数据必须满足规则,否则可能导致浏览器端无法接受到后续的推送(比如发送stream.write('str');)