Search code examples
javascriptsignalrsignalr.client

Getting SignalR code to run before handler code triggered during await invoke


Let's say I set up a JS SignalR connection to have a handler that responds to incoming messages from the server:

this.connection = new HubConnectionBuilder()
    .withUrl(this.hubUrl)
    .build();

this.connection.on("GameDataUpdatedV1", async (evt: GameDataUpdatedEvent) => {
    this.#handleGameDataUpdate(evt.updateData);
});

#handleGameDataUpdate = async (update: GameDataUpdate) => {
    console.log("Handler running...");
}

Now I await a SignalR call to the server:

try {
    console.log("About to invoke...");
    await this.connection.invoke("TestInvoke", { testData: 123 });
    console.log("Resumed from invoke.");
}
catch (err) {
    console.log("Error during invoke!");
    return;
}

The server sends GameDataUpdatedV1 messages every 2 seconds, and the TestInvoke takes about 10 seconds to run. What I get in the console is:

About to invoke...
Handler running...
Handler running...
Handler running...
Handler running...
Resumed from invoke.

I want the 'resumed from invoke' code to run before the handler calls, but it runs them before it runs the code that resumes after the invoke call has returned. How can I get it to run in the order I want?


Solution

  • This is because invoke awaits the response. You'd need to change to not await the TestInvoke command:

    console.log("About to invoke...");
    this.connection
        .invoke("TestInvoke", { testData: 123 })
        .then(() => {
           console.log("Invoke successfully completed");
        });
        .catch(() => {
           console.log("Error during invoke!");
        });
    
    // runs immediately after `invoke` is called, not awaiting response
    console.log("Resumed from invoke.");