Added IHubProtocol to ts client (#537)

- Mimics the .NET client structure wise
- Also adds a JsonHubProtocol implementation
This commit is contained in:
David Fowler 2017-06-07 05:46:27 -10:00 committed by GitHub
parent 0bbe42a912
commit 50f1d8f9fe
4 changed files with 61 additions and 47 deletions

View File

@ -3,36 +3,10 @@ import { IConnection } from "./IConnection"
import { Connection } from "./Connection" import { Connection } from "./Connection"
import { TransportType } from "./Transports" import { TransportType } from "./Transports"
import { Subject, Observable } from "./Observable" import { Subject, Observable } from "./Observable"
import * as Formatters from "./Formatters";
const enum MessageType {
Invocation = 1,
Result,
Completion
}
interface HubMessage {
readonly type: MessageType;
readonly invocationId: string;
}
interface InvocationMessage extends HubMessage {
readonly target: string;
readonly arguments: Array<any>;
readonly nonblocking?: boolean;
}
interface ResultMessage extends HubMessage {
readonly item?: any;
}
interface CompletionMessage extends HubMessage {
readonly error?: string;
readonly result?: any;
}
export { Connection } from "./Connection" export { Connection } from "./Connection"
export { TransportType } from "./Transports" export { TransportType } from "./Transports"
import { IHubProtocol, MessageType, HubMessage, CompletionMessage, ResultMessage, InvocationMessage } from "./IHubProtocol";
import { JsonHubProtocol } from "./JsonHubProtocol";
export class HubConnection { export class HubConnection {
private connection: IConnection; private connection: IConnection;
@ -40,6 +14,7 @@ export class HubConnection {
private methods: Map<string, (...args: any[]) => void>; private methods: Map<string, (...args: any[]) => void>;
private id: number; private id: number;
private connectionClosedCallback: ConnectionClosed; private connectionClosedCallback: ConnectionClosed;
private protocol: IHubProtocol;
static create(url: string, queryString?: string): HubConnection { static create(url: string, queryString?: string): HubConnection {
return new this(new Connection(url, queryString)) return new this(new Connection(url, queryString))
@ -59,22 +34,16 @@ export class HubConnection {
this.callbacks = new Map<string, (invocationEvent: CompletionMessage | ResultMessage) => void>(); this.callbacks = new Map<string, (invocationEvent: CompletionMessage | ResultMessage) => void>();
this.methods = new Map<string, (...args: any[]) => void>(); this.methods = new Map<string, (...args: any[]) => void>();
this.id = 0; this.id = 0;
this.protocol = new JsonHubProtocol();
} }
private onDataReceived(data: any) { private onDataReceived(data: any) {
// TODO: separate JSON parsing
// Can happen if a poll request was cancelled
if (!data) {
return;
}
// Parse the messages // Parse the messages
let messages = Formatters.TextMessageFormat.parse(data); let messages = this.protocol.parseMessages(data);
for (var i = 0; i < messages.length; ++i) { for (var i = 0; i < messages.length; ++i) {
console.log(`Received message: ${messages[i]}`); var message = messages[i];
var message = JSON.parse(messages[i]);
switch (message.type) { switch (message.type) {
case MessageType.Invocation: case MessageType.Invocation:
this.InvokeClientMethod(<InvocationMessage>message); this.InvokeClientMethod(<InvocationMessage>message);
@ -159,8 +128,7 @@ export class HubConnection {
} }
}); });
// TODO: separate conversion to enable different data formats let message = this.protocol.writeMessage(invocationDescriptor);
let message = this.framePayload(invocationDescriptor);
this.connection.send(message) this.connection.send(message)
.catch(e => { .catch(e => {
@ -190,8 +158,7 @@ export class HubConnection {
} }
}); });
// TODO: separate conversion to enable different data formats let message = this.protocol.writeMessage(invocationDescriptor);
let message = this.framePayload(invocationDescriptor);
this.connection.send(message) this.connection.send(message)
.catch(e => { .catch(e => {
@ -211,11 +178,6 @@ export class HubConnection {
this.connectionClosedCallback = callback; this.connectionClosedCallback = callback;
} }
private framePayload(invocationDescriptor: InvocationMessage): string {
let data = JSON.stringify(invocationDescriptor);
return Formatters.TextMessageFormat.write(data);
}
private createInvocation(methodName: string, args: any[]): InvocationMessage { private createInvocation(methodName: string, args: any[]): InvocationMessage {
let id = this.id; let id = this.id;
this.id++; this.id++;

View File

@ -0,0 +1,30 @@
export const enum MessageType {
Invocation = 1,
Result,
Completion
}
export interface HubMessage {
readonly type: MessageType;
readonly invocationId: string;
}
export interface InvocationMessage extends HubMessage {
readonly target: string;
readonly arguments: Array<any>;
readonly nonblocking?: boolean;
}
export interface ResultMessage extends HubMessage {
readonly item?: any;
}
export interface CompletionMessage extends HubMessage {
readonly error?: string;
readonly result?: any;
}
export interface IHubProtocol {
parseMessages(input: string): HubMessage[];
writeMessage(message: HubMessage): string;
}

View File

@ -0,0 +1,23 @@
import { TextMessageFormat } from "./Formatters";
import { IHubProtocol, HubMessage } from "./IHubProtocol";
export class JsonHubProtocol implements IHubProtocol {
parseMessages(input: string): HubMessage[] {
if (!input) {
return [];
}
// Parse the messages
let messages = TextMessageFormat.parse(input);
let hubMessages = [];
for (var i = 0; i < messages.length; ++i) {
hubMessages.push(JSON.parse(messages[i]));
}
return hubMessages;
}
writeMessage(message: HubMessage): string {
return TextMessageFormat.write(JSON.stringify(message));
}
}

View File

@ -13,7 +13,6 @@
<ItemGroup> <ItemGroup>
<Inputs Include="*.ts;" /> <Inputs Include="*.ts;" />
<Inputs Remove="Observable.ts" />
<Outputs Include="@(Inputs -> '$(SignalRClientDistFolder)src\%(FileName).d.ts')" /> <Outputs Include="@(Inputs -> '$(SignalRClientDistFolder)src\%(FileName).d.ts')" />
<Outputs Include="@(Inputs -> '$(SignalRClientDistFolder)src\%(FileName).js')" /> <Outputs Include="@(Inputs -> '$(SignalRClientDistFolder)src\%(FileName).js')" />
<Outputs Include="$(SignalRClientDistFolder)browser\signalr-client.js" /> <Outputs Include="$(SignalRClientDistFolder)browser\signalr-client.js" />