如何在超时后终止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
相关产品推荐
相关产品推荐

