mirror of
https://github.com/avatao-content/frontend-tutorial-framework
synced 2024-12-04 18:51:32 +00:00
Reconnect websockets automatically
This commit is contained in:
parent
d8545c48be
commit
ea5bf30a95
@ -5,7 +5,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve --proxy-config proxy.conf.json",
|
"start": "ng serve --proxy-config proxy.conf.json",
|
||||||
"build": "ng build --prod --aot --build-optimizer"
|
"build": "ng build --prod --aot --build-optimizer",
|
||||||
|
"lint": "ng lint --fix"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -8,11 +8,16 @@ export class TerminadoService {
|
|||||||
xterm: Terminal;
|
xterm: Terminal;
|
||||||
ws: WebSocket;
|
ws: WebSocket;
|
||||||
attached = false;
|
attached = false;
|
||||||
|
private dataListener: any;
|
||||||
|
private resizeListener: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
Terminal.applyAddon(fit);
|
Terminal.applyAddon(fit);
|
||||||
Terminal.applyAddon(terminado);
|
this.xterm = this.createTerminal();
|
||||||
this.xterm = new Terminal({
|
}
|
||||||
|
|
||||||
|
createTerminal() {
|
||||||
|
return new Terminal({
|
||||||
theme: {
|
theme: {
|
||||||
foreground: '#ffffff',
|
foreground: '#ffffff',
|
||||||
background: '#0C0C0C', // $tao-gray-800
|
background: '#0C0C0C', // $tao-gray-800
|
||||||
@ -37,26 +42,52 @@ export class TerminadoService {
|
|||||||
},
|
},
|
||||||
fontSize: 14
|
fontSize: 14
|
||||||
});
|
});
|
||||||
|
|
||||||
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
|
||||||
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(element: HTMLElement) {
|
attach(element: HTMLElement) {
|
||||||
|
if (this.attached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||||
|
this.ws = new WebSocket(wsproto + window.location.host + '/terminal');
|
||||||
|
|
||||||
this.ws.onopen = () => {
|
this.ws.onopen = () => {
|
||||||
(<any>this.xterm).terminadoAttach(this.ws);
|
this.attached = true;
|
||||||
|
this.xterm = this.createTerminal();
|
||||||
this.xterm.open(element);
|
this.xterm.open(element);
|
||||||
this.fit();
|
this.fit();
|
||||||
this.xterm.blur();
|
// In order to reset the terminal state after a broken socket, we need to register the listeners manually.
|
||||||
this.attached = true;
|
(<any>this.xterm)._core.register(this.dataListener = this.xterm.onData(data => {
|
||||||
|
this.ws.send(JSON.stringify(['stdin', data]));
|
||||||
|
}));
|
||||||
|
(<any>this.xterm)._core.register(this.resizeListener = this.xterm.onResize((size: { rows: number, cols: number }) => {
|
||||||
|
this.ws.send(JSON.stringify(['set_size', size.rows, size.cols]));
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
this.detach();
|
||||||
|
this.xterm.destroy();
|
||||||
|
this.attach(element);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onmessage = msg => {
|
||||||
|
const data = JSON.parse(msg.data);
|
||||||
|
if (data[0] === 'stdout') {
|
||||||
|
this.xterm.write(data[1]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
detach() {
|
detach() {
|
||||||
(<any>this.xterm).terminadoDetach(this.ws);
|
if (!this.attached) {
|
||||||
this.xterm.destroy();
|
return;
|
||||||
this.ws.close();
|
}
|
||||||
|
|
||||||
this.attached = false;
|
this.attached = false;
|
||||||
|
this.dataListener.dispose();
|
||||||
|
this.resizeListener.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
fit() {
|
fit() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subject, Subscription } from 'rxjs';
|
||||||
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
|
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
import { WebSocketMessage } from '../message-types/websocket-message';
|
import { WebSocketMessage } from '../message-types/websocket-message';
|
||||||
@ -17,14 +17,28 @@ export enum Intent {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class WebSocketService {
|
export class WebSocketService {
|
||||||
private ws: WebSocketSubject<WebSocketMessage>;
|
private ws: WebSocketSubject<WebSocketMessage>;
|
||||||
|
private subject: Subject<WebSocketMessage> = new Subject<WebSocketMessage>();
|
||||||
|
private subscription: Subscription;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
public connect() {
|
public connect() {
|
||||||
if (!this.ws) {
|
if (!this.ws) {
|
||||||
|
if (this.subscription) {
|
||||||
|
this.subscription.unsubscribe();
|
||||||
|
}
|
||||||
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
const wsproto = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||||
const connAddr = wsproto + window.location.host + '/ws';
|
const connAddr = wsproto + window.location.host + '/ws';
|
||||||
this.ws = webSocket<WebSocketMessage>(connAddr);
|
this.ws = webSocket<WebSocketMessage>({
|
||||||
|
url: connAddr,
|
||||||
|
closeObserver: {
|
||||||
|
next: closeEvent => {
|
||||||
|
this.ws = null;
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.subscription = this.ws.subscribe(msg => this.subject.next(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +49,7 @@ export class WebSocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public observeAll<T extends WebSocketMessage>(key: string): Observable<T> {
|
public observeAll<T extends WebSocketMessage>(key: string): Observable<T> {
|
||||||
return this.ws.pipe(
|
return this.subject.pipe(
|
||||||
filter(message => message.key.startsWith(key)),
|
filter(message => message.key.startsWith(key)),
|
||||||
map(message => <T> message)
|
map(message => <T> message)
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user