123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- export interface Command {
- command: string
- task_id: string
- spec: any
- }
- export interface ClientEvent {
- event: string,
- task_id: string,
- data: any
- }
- /*
- * 会话
- * 向外暴露的事件:on_session_create、on_session_close、on_server_message
- * 提供的函数:start_session、send_message、close_session
- * */
- export interface Session {
- on_session_create(callback: () => void): void;
- on_session_close(callback: () => void): void;
- on_server_message(callback: (msg: Command) => void): void;
- start_session(debug: boolean): void;
- send_message(msg: ClientEvent, onprogress?: (loaded: number, total: number) => void): void;
- close_session(): void;
- closed(): boolean;
- }
- export class WebSocketSession implements Session {
- ws: WebSocket;
- debug: boolean;
- private _closed: boolean;
- private _on_session_create: (this: WebSocket, ev: Event) => any = () => {
- };
- private _on_session_close: (this: WebSocket, ev: CloseEvent) => any = () => {
- };
- private _on_server_message: (msg: Command) => any = () => {
- };
- constructor(public ws_api: string, app_name: string = 'index') {
- this.ws = null;
- this.debug = false;
- this._closed = false;
- let url = new URL(ws_api);
- if (url.protocol !== 'wss:' && url.protocol !== 'ws:') {
- let protocol = url.protocol || window.location.protocol;
- url.protocol = protocol.replace('https', 'wss').replace('http', 'ws');
- }
- url.search = "?app=" + app_name;
- this.ws_api = url.href;
- }
- on_session_create(callback: () => any): void {
- this._on_session_create = callback;
- };
- on_session_close(callback: () => any): void {
- this._on_session_close = callback;
- }
- on_server_message(callback: (msg: Command) => any): void {
- this._on_server_message = callback;
- }
- start_session(debug: boolean = false): void {
- this.debug = debug;
- this.ws = new WebSocket(this.ws_api);
- this.ws.onopen = this._on_session_create;
- this.ws.onclose = this._on_session_close;
- let that = this;
- this.ws.onmessage = function (evt) {
- let msg: Command = JSON.parse(evt.data);
- if (debug) console.info('>>>', msg);
- that._on_server_message(msg);
- };
- }
- start_onprogress(onprogress?: (loaded: number, total: number) => void): void {
- let total = this.ws.bufferedAmount;
- let onprogressID = setInterval(() => {
- let loaded = total - this.ws.bufferedAmount;
- onprogress(loaded, total);
- if (this.ws.bufferedAmount == 0)
- clearInterval(onprogressID);
- }, 200);
- }
- send_message(msg: ClientEvent, onprogress?: (loaded: number, total: number) => void): void {
- if (this.closed())
- return alert("与服务器连接已断开,请刷新页面重新操作");
- if (this.ws === null)
- return console.error('WebSocketWebIOSession.ws is null when invoke WebSocketWebIOSession.send_message. ' +
- 'Please call WebSocketWebIOSession.start_session first');
- this.ws.send(JSON.stringify(msg));
- if (onprogress)
- this.start_onprogress(onprogress);
- if (this.debug) console.info('<<<', msg);
- }
- close_session(): void {
- this._closed = true;
- this._on_session_close.call(this.ws, null);
- try {
- this.ws.close()
- } catch (e) {
- }
- }
- closed(): boolean {
- return this._closed || this.ws.readyState === WebSocket.CLOSED || this.ws.readyState === WebSocket.CLOSING;
- }
- }
- export class HttpSession implements Session {
- interval_pull_id: number = null;
- webio_session_id: string;
- debug = false;
- private _closed = false;
- private _on_session_create: () => void = () => {
- };
- private _on_session_close: () => void = () => {
- };
- private _on_server_message: (msg: Command) => void = () => {
- };
- constructor(public api_url: string, app_name = 'index', public pull_interval_ms = 1000) {
- let url = new URL(api_url, window.location.href);
- url.search = "?app=" + app_name;
- this.api_url = url.href;
- }
- on_session_create(callback: () => void): void {
- this._on_session_create = callback;
- }
- on_session_close(callback: () => void): void {
- this._on_session_close = callback;
- }
- on_server_message(callback: (msg: Command) => void): void {
- this._on_server_message = callback;
- }
- start_session(debug: boolean = false): void {
- this.debug = debug;
- let that = this;
- function pull() {
- $.ajax({
- type: "GET",
- url: that.api_url,
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- headers: {"webio-session-id": that.webio_session_id},
- success: function (data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
- that._on_request_success(data, textStatus, jqXHR);
- that._on_session_create();
- },
- error: function () {
- console.error('Http pulling failed');
- }
- })
- }
- pull();
- this.interval_pull_id = setInterval(pull, this.pull_interval_ms);
- }
- private _on_request_success(data: Command[], textStatus: string, jqXHR: JQuery.jqXHR) {
- let sid = jqXHR.getResponseHeader('webio-session-id');
- if (sid) this.webio_session_id = sid;
- for (let msg of data) {
- if (this.debug) console.info('>>>', msg);
- this._on_server_message(msg);
- }
- };
- send_message(msg: ClientEvent, onprogress?: (loaded: number, total: number) => void): void {
- if (this.closed())
- return alert("与服务器连接已断开,请刷新页面重新操作");
- if (this.debug) console.info('<<<', msg);
- $.ajax({
- type: "POST",
- url: this.api_url,
- data: JSON.stringify(msg),
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- headers: {"webio-session-id": this.webio_session_id},
- success: this._on_request_success.bind(this),
- xhr: function () {
- let xhr = new window.XMLHttpRequest();
- // Upload progress
- xhr.upload.addEventListener("progress", function (evt) {
- if (evt.lengthComputable && onprogress) {
- onprogress(evt.loaded, evt.total);
- }
- }, false);
- return xhr;
- },
- error: function () { // todo
- console.error('Http push event failed, event data: %s', msg);
- }
- });
- }
- close_session(): void {
- this._closed = true;
- this._on_session_close();
- clearInterval(this.interval_pull_id);
- }
- closed(): boolean {
- return this._closed;
- }
- }
- /*
- * Check given `backend_addr` is a http backend
- * Usage:
- * // `http_backend` is a boolean to present whether or not a http_backend the given `backend_addr` is
- * is_http_backend('http://localhost:8080/io').then(function(http_backend){ });
- * */
- export function is_http_backend(backend_addr: string) {
- let url = new URL(backend_addr);
- let protocol = url.protocol || window.location.protocol;
- url.protocol = protocol.replace('wss', 'https').replace('ws', 'http');
- backend_addr = url.href;
- return new Promise(function (resolve, reject) {
- $.get(backend_addr, {test: 1}, undefined, 'html').done(function (data: string) {
- resolve(data === 'ok');
- }).fail(function (e: JQuery.jqXHR) {
- resolve(false);
- });
- });
- }
|