You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在超时后终止Angular WebSocket的连接建立请求

解决Angular WebSocket连接超时终止的问题

嘿,这个问题我之前也踩过坑!其实你可能忽略了一个关键点:即使WebSocket处于CONNECTING状态(readyState=0),调用ws.close()依然可以终止正在进行的连接建立请求,这是浏览器WebSocket API支持的标准行为,完全能满足你的需求。

接下来我会基于你的websocket.service.ts代码,给出完整的修改方案:

1. 核心修改:超时终止连接+状态标记

我们可以在create方法里添加超时逻辑,同时标记是否是超时导致的关闭,方便后续通知客户端:

import { Injectable } from '@angular/core';
import * as Rx from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class WebsocketService {
  constructor() { }

  private subject: Rx.Subject<MessageEvent>;
  // 新增:标记是否是超时关闭
  private isTimeoutClose = false;

  public connect(url): Rx.Subject<MessageEvent> {
    if (!this.subject) {
      this.subject = this.create(url);
      console.log('Successfully connected: ' + url);
    }
    return this.subject;
  }

  private create(url): Rx.Subject<MessageEvent> {
    const ws = new WebSocket(url);
    this.isTimeoutClose = false;

    // 设置超时(这里用5秒示例,你可以改成10秒)
    const timeoutTimer = setTimeout(() => {
      if (ws.readyState === WebSocket.CONNECTING) {
        this.isTimeoutClose = true;
        ws.close(); // 直接调用close终止连接请求
        console.log('WebSocket连接超时,已终止请求');
      }
    }, 5000);

    const observable = Rx.Observable.create((obs: Rx.Observer<MessageEvent>) => {
      ws.onmessage = (event) => {
        // 连接成功后清除超时定时器
        clearTimeout(timeoutTimer);
        obs.next(event);
      };
      
      ws.onerror = (error) => {
        clearTimeout(timeoutTimer);
        obs.error(error);
      };
      
      ws.onclose = (event) => {
        clearTimeout(timeoutTimer);
        // 如果是超时导致的关闭,通知客户端
        if (this.isTimeoutClose) {
          obs.error(new Error('WebSocket连接超时,已终止请求'));
        } else {
          obs.complete();
        }
      };

      return () => {
        ws.close();
      };
    });

    const observer = {
      next: (data: Object) => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(JSON.stringify(data));
        }
      }
    };

    return Rx.Subject.create(observer, observable);
  }
}

2. 关键细节说明

  • 超时终止逻辑:在定时器中判断readyState为CONNECTING(即0)时,调用ws.close(),浏览器会立即取消连接尝试,触发onclose事件。
  • 清除定时器:不管连接成功、失败还是超时,都要清除超时定时器,避免内存泄漏。
  • 客户端通知:通过isTimeoutClose标记区分超时关闭和正常关闭,在onclose中给观察者发送错误信息,这样使用该服务的组件就能捕获到超时事件,提示用户。

3. 组件中使用示例

在你的组件里订阅WebSocket服务时,可以捕获超时错误:

import { Component, OnInit } from '@angular/core';
import { WebsocketService } from './websocket.service';

@Component({
  selector: 'app-root',
  template: '<div>{{connectionStatus}}</div>'
})
export class AppComponent implements OnInit {
  connectionStatus = '';

  constructor(private wsService: WebsocketService) {}

  ngOnInit() {
    const wsSubject = this.wsService.connect('ws://your-server-url');
    wsSubject.subscribe({
      next: (event) => {
        this.connectionStatus = '连接成功,接收数据:' + event.data;
      },
      error: (err) => {
        this.connectionStatus = err.message;
        // 可以在这里重置subject,方便后续重新连接
        // this.wsService['subject'] = null;
      },
      complete: () => {
        this.connectionStatus = '连接已正常关闭';
      }
    });
  }
}

这样就能完美实现“连接超时10秒后终止请求并通知客户端”的需求啦!

内容的提问来源于stack exchange,提问作者Sravani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:13:10