在我的 Angular 2 项目中,我使用 ng2-stomp-service 建立到服务器的套接字连接。
大多数时候它工作正常,但有时我在尝试订阅套接字时会收到此错误,说我的连接尚未建立:
Error: Uncaught (in promise): Error: InvalidStateError: The connection has not been established yet Error: InvalidStateError: The connection has not been established yet
at SockJS.send (main.js:158)
at Client._transmit (stomp.js:159)
at Client.subscribe (stomp.js:379)
at StompService.subscribe (stomp.service.ts:132)
at slide-manager.service.ts:129
at ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.es5.js:3933)
at ZoneDelegate.invoke (zone.js:390)
at Zone.run (zone.js:141)
at zone.js:818
at SockJS.send (main.js:158)
at Client._transmit (stomp.js:159)
at Client.subscribe (stomp.js:379)
at StompService.subscribe (stomp.service.ts:132)
at slide-manager.service.ts:129
at ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.es5.js:3933)
at ZoneDelegate.invoke (zone.js:390)
at Zone.run (zone.js:141)
at zone.js:818
at resolvePromise (zone.js:770)
at zone.js:821
at ZoneDelegate.invokeTask (zone.js:424)
at Object.onInvokeTask (core.es5.js:3924)
at ZoneDelegate.invokeTask (zone.js:423)
at Zone.runTask (zone.js:191)
at drainMicroTaskQueue (zone.js:584)
at WebSocket.ZoneTask.invoke (zone.js:490)
这个堆栈跟踪中属于我的部分是slide-manager.service.ts:129。该代码位于该代码的 stomp.subscribe 行:
this.socketConfig = {
host: 'http://' + getHost() + '/app-ws',
debug: true,
queue: {'init': false}
};
this.stomp.configure(this.socketConfig);
this.stomp.startConnect().then((frame) => {
this.stomp.done('init');
this.connected = true;
this.spectraSubscription = this.stomp.subscribe('/topic/spectra', (spectra) => {
if (spectra && (!this.theChart || hostElement.childElementCount === 0) && !this.refreshFlag) {
this.makeChart(spectra.points, hostElement);
this.refreshFlag = true;
} else if (spectra && (this.theChart || hostElement.childElementCount > 0) || this.refreshFlag) {
this.theChart.collectionView.sourceCollection = spectra.points;
this.theChart.collectionView.refresh();
}
});
如何确保在尝试执行 .subscribe() 之前确实建立了连接?我认为将它放在 .then() 块中可以解决问题,因为它只能在连接的承诺解决后执行,但显然即使不存在连接它仍然会被触发(根据错误)。
或者这里还有更多我错过的事情吗?
我能够通过检查 stomp 客户端的内置“状态”属性来解决此问题:
if (this.stomp.status === 'CONNECTED') {
// do stuff that requires a connection, like establish subscriptions
}
对于某些用例,您可能需要暂停,直到建立连接,然后才继续。你可以使用这样的东西
const awaitConnect = async (awaitConnectConfig) => {
const {
retries = 3,
curr = 0,
timeinterval = 100,
} = awaitConnectConfig || {};
return new Promise((resolve, reject) => {
console.log(timeinterval);
setTimeout(() => {
if (this.connected) {
resolve();
} else {
console.log("failed to connect! retrying");
if (curr >= retries) {
console.log("failed to connect within the specified time interval");
reject();
}
this.awaitConnect({ ...awaitConnectConfig, curr: curr + 1 });
}
}, timeinterval);
});
};
然后调用它
await awaitConnect()
这将阻塞主线程,直到建立底层 Web 套接字连接,并将每隔
timeinterval
毫秒检查状态,直到 retries
耗尽