SSE发射器多次触发,有时浏览器没有得到事件

问题描述:

我在node.js/express应用程序中设置了一个事件发射器。它发出的事件,被前端听众抓住。事情是,虽然我可以看到发射被调用一次,但发射器发出相同的事件高达4次。另外,虽然一般情况下,听众收到事件并采取行动,但有时没有任何反应。有没有人知道我做错了什么?SSE发射器多次触发,有时浏览器没有得到事件

后端:

app.get('/getStatus', isLoggedIn, function(req, res){ 
res.writeHead(200, {'Content-Type': 'text/event-stream'}); 
progressEmitter.on('status',function(newState, job_id, fTime, jobLink){ 
    console.log('Updated state to : ' + newState + ' for job ' + job_id); 
    res.write("event: state\n"); 
    res.write(`data:${newState},${job_id},${fTime},${jobLink}\n\n`); 
    console.log(`Emitted state change data! :${newState},${job_id},${fTime},${jobLink}\n\n`); 
}); 

});

前端:

$(document).ready(function() { 
var state = []; 
var source = new EventSource('getStatus'); 
source.addEventListener('state', function(e) { 
    state = e.data.split(','); 
    for (var ajob in jobsReceived){ 
     if (jobsReceived[ajob].id == state[1]) { 
      jobsReceived[ajob].status = state[0]; 
      jobsReceived[ajob].finished_time = state[2]; 
      console.log(state[0]); 
      if (state[0] === 'saved') jobsReceived[ajob].link = state[3]; 
      break; 
     } 
    } 
    $('#table').bootstrapTable('updateByUniqueId', { 
      id: state[1], 
      row: { 
       status: format_status(state[0]), 
       finished_time: state[2], 
       link: state[0] === 'saved'? state[3]:'' 
      } 
     }); 

}); 

在其他问题上花费的时间后,我决定用清醒的头脑重新审视它,并最终得到了解决。我在这里发布,以防有​​人遇到同样的问题。

这里发生的是,每次调用progressEmitter.on()时都会添加一个侦听器。当事件发出时,所有监听器都会运行。

为了解决这个问题,当请求关闭时,监听器必须被移除。这通过调用emitter.removeListener()来完成。由于此函数所需的参数是事件名称和侦听器函数,因此更容易命名侦听器函数。因此,后端代码更改如下:

app.get('/getStatus', isLoggedIn, function(req, res){ 
    res.writeHead(200, {'Content-Type': 'text/event-stream'}); 
    function statusEvent(newState, job_id, fTime, jobLink){ 
    console.log('Updated state to : ' + newState + ' for job ' + job_id); 
    res.write("event: state\n"); 
    res.write(`data:${newState},${job_id},${fTime},${jobLink}\n\n`); 
    console.log(`Emitted state change data!'); 
} 

    progressEmitter.on('status',statusEvent); 
    req.on('close', function(){ 
    progressEmitter.removeListener('event', statusEvent); 
    }) 
})