gpt4 book ai didi

javascript - Angular 8 - 在错误时处理 SSE 重新连接

转载 作者:行者123 更新时间:2023-12-01 15:17:41 26 4
gpt4 key购买 nike

我正在开发一个 Angular 8(使用 Electron 6 和 Ionic 4)项目,现在我们正处于评估阶段,我们正在决定是否用 SSE(服务器发送的事件)或 Web 套接字替换轮询。我的部分工作是研究 SSE。

我创建了生成随机数的小型 express 应用程序,一切正常。唯一让我烦恼的是在服务器错误时重新连接的正确方法。

我的实现如下所示:

  private createSseSource(): Observable<MessageEvent> {
return Observable.create(observer => {
this.eventSource = new EventSource(SSE_URL);
this.eventSource.onmessage = (event) => {
this.zone.run(() => observer.next(event));
};

this.eventSource.onopen = (event) => {
console.log('connection open');
};

this.eventSource.onerror = (error) => {
console.log('looks like the best thing to do is to do nothing');
// this.zone.run(() => observer.error(error));
// this.closeSseConnection();
// this.reconnectOnError();
};
});
}

我试图实现 reconnectOnError()此函数后 answer ,但我只是无法使其工作。然后我放弃了 reconnectOnError()功能,似乎这是一件更好的事情。不要尝试关闭并重新连接,也不要将错误传播到 observable。只需坐下来等待,当服务器再次运行时,它将自动重新连接。

问题是,这真的是最好的做法吗? 需要提到的重要一点是,FE 应用程序与它自己的服务器通信,该服务器不能被另一个应用程序实例(内置设备)访问。

最佳答案

我看到我的问题得到了一些关注,所以我决定发布我的解决方案。回答我的问题:“这真的是最好的做法,省略重新连接功能吗?”我不知道 :)。但是这个解决方案对我有用,并且在生产中得到了证明,它提供了在某种程度上实际控制 SSE 重新连接的方法。

这是我所做的:

  • 重写 createSseSource函数,因此返回类型为 void
  • 来自 SSE 的数据不是返回 observable,而是馈送到主题/NgRx 操作
  • 已添加公共(public) openSseChannel和私有(private) reconnectOnError更好的控制功能
  • 新增私有(private)功能processSseEvent处理自定义消息类型

  • 由于我在这个项目上使用 NgRx,每个 SSE 消息都会发送相应的操作,但这可以替换为 ReplaySubject并公开为 observable .
    // Public function, initializes connection, returns true if successful
    openSseChannel(): boolean {
    this.createSseEventSource();
    return !!this.eventSource;
    }

    // Creates SSE event source, handles SSE events
    protected createSseEventSource(): void {
    // Close event source if current instance of SSE service has some
    if (this.eventSource) {
    this.closeSseConnection();
    this.eventSource = null;
    }
    // Open new channel, create new EventSource
    this.eventSource = new EventSource(this.sseChannelUrl);

    // Process default event
    this.eventSource.onmessage = (event: MessageEvent) => {
    this.zone.run(() => this.processSseEvent(event));
    };

    // Add custom events
    Object.keys(SSE_EVENTS).forEach(key => {
    this.eventSource.addEventListener(SSE_EVENTS[key], event => {
    this.zone.run(() => this.processSseEvent(event));
    });
    });

    // Process connection opened
    this.eventSource.onopen = () => {
    this.reconnectFrequencySec = 1;
    };

    // Process error
    this.eventSource.onerror = (error: any) => {
    this.reconnectOnError();
    };
    }

    // Processes custom event types
    private processSseEvent(sseEvent: MessageEvent): void {
    const parsed = sseEvent.data ? JSON.parse(sseEvent.data) : {};
    switch (sseEvent.type) {
    case SSE_EVENTS.STATUS: {
    this.store.dispatch(StatusActions.setStatus({ status: parsed }));
    // or
    // this.someReplaySubject.next(parsed);
    break;
    }
    // Add others if neccessary
    default: {
    console.error('Unknown event:', sseEvent.type);
    break;
    }
    }
    }

    // Handles reconnect attempts when the connection fails for some reason.
    // const SSE_RECONNECT_UPPER_LIMIT = 64;
    private reconnectOnError(): void {
    const self = this;
    this.closeSseConnection();
    clearTimeout(this.reconnectTimeout);
    this.reconnectTimeout = setTimeout(() => {
    self.openSseChannel();
    self.reconnectFrequencySec *= 2;
    if (self.reconnectFrequencySec >= SSE_RECONNECT_UPPER_LIMIT) {
    self.reconnectFrequencySec = SSE_RECONNECT_UPPER_LIMIT;
    }
    }, this.reconnectFrequencySec * 1000);
    }

    由于 SSE 事件被馈送到主题/操作,因此连接是否丢失并不重要,因为至少最后一个事件保留在主题或存储中。然后可以静默尝试重新连接,并且当发送新数据时,会无缝处理。

    关于javascript - Angular 8 - 在错误时处理 SSE 重新连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58075434/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com