Enabling multiple callbacks for HubConnection.onClose

Fixes: #842
This commit is contained in:
Pawel Kadluczka 2017-09-19 14:09:24 -07:00
parent a7fb243501
commit 5ca089e33e
3 changed files with 49 additions and 14 deletions

View File

@ -391,6 +391,40 @@ describe("HubConnection", () => {
expect(await observer.completed).toEqual([1, 2, 3]); expect(await observer.completed).toEqual([1, 2, 3]);
}); });
}); });
describe("onClose", () => {
it("it can have multiple callbacks", async () => {
let connection = new TestConnection();
let hubConnection = new HubConnection(connection);
let invocations = 0;
hubConnection.onClosed(e => invocations++);
hubConnection.onClosed(e => invocations++);
// Typically this would be called by the transport
connection.onClosed();
expect(invocations).toBe(2);
});
it("callbacks receive error", async () => {
let connection = new TestConnection();
let hubConnection = new HubConnection(connection);
let error: Error;
hubConnection.onClosed(e => error = e);
// Typically this would be called by the transport
connection.onClosed(new Error("Test error."));
expect(error.message).toBe("Test error.");
});
it("ignores null callbacks", async () => {
let connection = new TestConnection();
let hubConnection = new HubConnection(connection);
hubConnection.onClosed(null);
hubConnection.onClosed(undefined);
// Typically this would be called by the transport
connection.onClosed();
// expect no errors
});
});
}); });
class TestConnection implements IConnection { class TestConnection implements IConnection {

View File

@ -27,7 +27,7 @@ export class HubConnection {
private callbacks: Map<string, (invocationUpdate: CompletionMessage | ResultMessage) => void>; private callbacks: Map<string, (invocationUpdate: CompletionMessage | ResultMessage) => void>;
private methods: Map<string, ((...args: any[]) => void)[]>; private methods: Map<string, ((...args: any[]) => void)[]>;
private id: number; private id: number;
private connectionClosedCallback: ConnectionClosed; private closedCallbacks: ConnectionClosed[];
constructor(urlOrConnection: string | IConnection, options: IHubConnectionOptions = {}) { constructor(urlOrConnection: string | IConnection, options: IHubConnectionOptions = {}) {
options = options || {}; options = options || {};
@ -44,12 +44,13 @@ export class HubConnection {
this.connection.onDataReceived = data => { this.connection.onDataReceived = data => {
this.onDataReceived(data); this.onDataReceived(data);
}; };
this.connection.onClosed = (error: Error) => { this.connection.onClosed = (error?: Error) => {
this.onConnectionClosed(error); this.onConnectionClosed(error);
} }
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.closedCallbacks = [];
this.id = 0; this.id = 0;
} }
@ -94,7 +95,7 @@ export class HubConnection {
} }
} }
private onConnectionClosed(error: Error) { private onConnectionClosed(error?: Error) {
let errorCompletionMessage = <CompletionMessage>{ let errorCompletionMessage = <CompletionMessage>{
type: MessageType.Completion, type: MessageType.Completion,
invocationId: "-1", invocationId: "-1",
@ -106,9 +107,7 @@ export class HubConnection {
}); });
this.callbacks.clear(); this.callbacks.clear();
if (this.connectionClosedCallback) { this.closedCallbacks.forEach(c => c.apply(this, [error]));
this.connectionClosedCallback(error);
}
} }
async start(): Promise<void> { async start(): Promise<void> {
@ -239,8 +238,10 @@ export class HubConnection {
} }
} }
set onClosed(callback: ConnectionClosed) { onClosed(callback: ConnectionClosed) {
this.connectionClosedCallback = callback; if (callback) {
this.closedCallbacks.push(callback);
}
} }
private createInvocation(methodName: string, args: any[], nonblocking: boolean): InvocationMessage { private createInvocation(methodName: string, args: any[], nonblocking: boolean): InvocationMessage {

View File

@ -18,10 +18,10 @@ describe('hubConnection', function () {
logging: signalR.LogLevel.Trace logging: signalR.LogLevel.Trace
}; };
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options); var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
hubConnection.onClosed = function (error) { hubConnection.onClosed(function (error) {
expect(error).toBe(undefined); expect(error).toBe(undefined);
done(); done();
}; });
hubConnection.start().then(function () { hubConnection.start().then(function () {
hubConnection.invoke('Echo', message).then(function (result) { hubConnection.invoke('Echo', message).then(function (result) {
@ -46,10 +46,10 @@ describe('hubConnection', function () {
}; };
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options); var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
hubConnection.onClosed = function (error) { hubConnection.onClosed(function (error) {
expect(error).toBe(undefined); expect(error).toBe(undefined);
done(); done();
}; });
var received = []; var received = [];
hubConnection.start().then(function () { hubConnection.start().then(function () {
@ -172,10 +172,10 @@ describe('hubConnection', function () {
}; };
var hubConnection = new signalR.HubConnection('http://' + document.location.host + '/uncreatable', options); var hubConnection = new signalR.HubConnection('http://' + document.location.host + '/uncreatable', options);
hubConnection.onClosed = function (error) { hubConnection.onClosed(function (error) {
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]); expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);
done(); done();
}; });
hubConnection.start(); hubConnection.start();
}); });
}); });