botframework-streaming
Version:
Streaming library for the Microsoft Bot Framework
128 lines (114 loc) • 4.01 kB
text/typescript
/**
* @module botframework-streaming
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { IBrowserFileReader, IBrowserWebSocket, INodeBuffer, ISocket } from '../interfaces';
/**
* Represents a WebSocket that implements [ISocket](xref:botframework-streaming.ISocket).
*/
export class BrowserWebSocket implements ISocket {
private webSocket: IBrowserWebSocket;
/**
* Creates a new instance of the [BrowserWebSocket](xref:botframework-streaming.BrowserWebSocket) class.
*
* @param socket The socket object to build this connection on.
*/
constructor(socket?: IBrowserWebSocket) {
if (socket) {
this.webSocket = socket;
}
}
/**
* Connects to the supporting socket using WebSocket protocol.
*
* @param serverAddress The address the server is listening on.
* @returns A Promise that resolves the websocket is open and rejects if an error is encountered.
*/
async connect(serverAddress: string): Promise<void> {
let resolver: (value: void | PromiseLike<void>) => void;
let rejector: (reason?: any) => void;
if (!this.webSocket) {
this.webSocket = new WebSocket(serverAddress);
}
this.webSocket.onerror = (e): void => {
rejector(e);
};
this.webSocket.onopen = (e): void => {
resolver(e);
};
return new Promise<void>((resolve, reject): void => {
resolver = resolve;
rejector = reject;
});
}
/**
* Indicates if the [BrowserWebSocket's](xref:botframework-streaming.BrowserWebSocket) underlying websocket is currently connected.
*
* @returns `true` if the underlying websocket is ready and availble to send messages, otherwise `false`.
*/
get isConnected(): boolean {
return this.webSocket.readyState === 1;
}
/**
* Writes a buffer to the socket and sends it.
*
* @param buffer The buffer of data to send across the connection.
*/
write(buffer: INodeBuffer): void {
this.webSocket.send(buffer);
}
/**
* Close the socket.
*/
close(): void {
this.webSocket.close();
}
/**
* Set the handler for text and binary messages received on the socket.
*
* @param handler The callback to handle the "message" event.
*/
setOnMessageHandler(handler: (x: any) => void): void {
const bufferKey = 'buffer';
const packets = [];
this.webSocket.onmessage = (evt): void => {
const fileReader = new FileReader();
const queueEntry = { buffer: null };
packets.push(queueEntry);
fileReader.onload = (e): void => {
const t = e.target as unknown as IBrowserFileReader;
queueEntry[bufferKey] = t.result;
if (packets[0] === queueEntry) {
while (0 < packets.length && packets[0][bufferKey]) {
handler(packets[0][bufferKey]);
packets.splice(0, 1);
}
}
};
fileReader.readAsArrayBuffer(evt.data);
};
}
/**
* Set the callback to call when encountering errors.
*
* @param handler The callback to handle the "error" event.
*/
setOnErrorHandler(handler: (x: any) => void): void {
this.webSocket.onerror = (error): void => {
if (error) {
handler(error);
}
};
}
/**
* Set the callback to call when encountering socket closures.
*
* @param handler The callback to handle the "close" event.
*/
setOnCloseHandler(handler: (x: any) => void): void {
this.webSocket.onclose = handler;
}
}