【发布时间】:2021-07-09 00:34:35
【问题描述】:
目标:在我的 Angular 应用程序中使用服务器发送的事件和 Express 后端
问题:服务器发送的事件没有到达客户端
后端代码router.get('/options/:a/:b/:c', async (req, res) => {
console.log('options endpoint called..', req.params.a,req.params.b,req.params.c);
// ---- SERVER SENT EVENTS ---- //
// Setting Headers
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // flush the headers to establish SSE with client
for(let i=0;i<10;i++){
console.log("should now send this response...banane")
res.write('banane!')
}
});
客户端代码
export class NetworkingService {
BASE_URL;
OPTIONS = 'options'
searchResultSubject: Subject<SearchResults>;
constructor(private http: HttpClient, private ls: LoggingService, private _zone: NgZone) { // shortened }
getOptions(a: string, b: string, c: string) {
this.ls.log("get options endpoint about to be triggered")
this.getServerSentEvent(this.BASE_URL + this.OPTIONS + "/" + a + "/" + b + "/" + c).subscribe(resp => {
this.ls.log("got from server: ", resp)
});
return this.searchResultSubject;
}
getServerSentEvent(url: string): Observable<any> {
console.log('creating an eventsource...')
return new Observable(observer => {
const eventSource = this.getEventSource(url);
eventSource.onopen = event => {
console.log('opening connection', eventSource.readyState)
};
eventSource.onmessage = event => {
console.log('event from server..')
this._zone.run(() => {
observer.next(event);
});
};
eventSource.onerror = error => {
console.log('error from server..')
this._zone.run(() => {
observer.error(error);
});
};
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
服务器端日志输出(如预期)
options endpoint called.. A B C
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
客户端日志输出(与预期不同)
get options endpoint about to be triggered
creating an eventsource...
opening connection 1
...然后什么都没有。
我尝试了什么?
我看不出我与这些有什么不同:so-question、tutorial、tutorial 在开发工具的网络选项卡中,我看到状态 200,键入带有正确标题的事件源行条目。但只有一个!
我认为我犯了一个非常明显的错误,因为它几乎可以正常工作,并且从示例中看起来很简单。 我的 Angular 是 10.1.6,快递是 4.17.1 我是直接与 ngZone 交互的新手,是否存在潜在错误?
按照here的建议,即使我注释掉压缩库或使用 res.flush(),问题仍然存在。
【问题讨论】:
-
在教程中 res.send() 也不存在。只有res.write。如果我使用 res.send,我会遇到一条错误消息 ~“发送响应后设置的标头”。据我了解 res.send() 用于正常响应,因为它是 res.write 和 res.end 的简写,在这种情况下应该使用“res.write()”,因为我可能有很多响应要写回客户端并且还不想 .end()。
-
更新:我最终使用了一个库 npmjs.com/package/@toverux/expresse,如下所示:stackoverflow.com/questions/34657222/… 有效,但我仍然不知道我哪里出错了。