Question

We have a signalR hub and JavaScript client. On the client, we call the "start" method on the hub proxy, which is sent to the server. The server pushes several messages to the client as they become ready, and then finishes. We expect to see the sequence "Invoking ... event ... event ... event ... Invoked", but what we see is often "Invoking ... event ... event ... Invoked ... event".

This is bad since the JavaScript code that happens after the hub invoke is done is not reliable place to stop listening and generate a final summary - if we stop listening for messages here, there's a good chance that we can lose data and show "95% complete".

i.e.

errorsHub.invoke('start', requestData)
  .done(function() { 
    // this will lose data
    errorsHub.off('errorsUpdate');
    showFinalSummary();
    });

Without the "off", the console debug message look like this:

[14:36:23 GMT+0100 (GMT Standard Time)] SignalR: Invoking errorshub.start
[14:36:23 GMT+0100 (GMT Standard Time)] SignalR: Triggering client hub event 'errorsUpdate' on hub 'ErrorsHub'.
...
[14:36:24 GMT+0100 (GMT Standard Time)] SignalR: Invoked errorshub.start
[14:36:24 GMT+0100 (GMT Standard Time)] SignalR: Triggering client hub event 'errorsUpdate' on hub 'ErrorsHub'.

Sometimes the last update come shortly after "invoked", but it can be up to 6 seconds later. Often we lose the last update, sometime we lose two.

The problem is much more frequent in Firefox than in Chrome. We are defaulting to the long polling transport since the server is IIS 7.5

If the "Invoked, call done" message is sent down the same pipe as the updates, how can it then overtake the last update in the pipe? On the server, when we call destination.errorsUpdate(someData), is this sent and acknowledged, sent or just queued up to send? If it's just queued, is there a way to flush the connection from the server, to make sure that the last update has been sent?

Would we be better off in the JavaScript client ignoring invoke(...).done entirely and checking in the updates for a special message signalling completion?

Was it helpful?

Solution

The done() handler is called when the server-side method has returned, but it doesn't guarantee that any async actions triggered by the server-side method have completed (calling client hub methods doesn't happen in the same Task that handles the server-side hub method, the message is simply queued and then later handled by the message bus).

I'm not sure what you're trying to do, so it's difficult to give targeted advice; a simple solution would be to create a client hub method showFinalSummary() which triggers what you're currently doing in the done() handler, then call this method from the server whenever appropriate (e.g. once you've sent all the error updates).

Your approach:

checking in the updates for a special message signalling completion

would also work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top