ASP.NET Core SignalR JavaScript クライアントASP.NET Core SignalR JavaScript client

作成者: Rachel AppelBy Rachel Appel

ASP.NET Core SignalR JavaScript クライアント ライブラリでは、サーバー側ハブのコードを呼び出すことができます。The ASP.NET Core SignalR JavaScript client library enables developers to call server-side hub code.

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

SignalR クライアント パッケージをインストールします。Install the SignalR client package

SignalR JavaScript クライアント ライブラリとして提供される、 npmパッケージ。The SignalR JavaScript client library is delivered as an npm package. Visual Studio を使用している場合は、実行npm installから、パッケージ マネージャー コンソールルート フォルダー内で。If you're using Visual Studio, run npm install from the Package Manager Console while in the root folder. Visual Studio Code でからのコマンドを実行、統合ターミナルします。For Visual Studio Code, run the command from the Integrated Terminal.

npm init -y
npm install @aspnet/signalr

npm のインストール パッケージの内容を node_modules\@aspnet\signalr\dist\browser フォルダー。npm installs the package contents in the node_modules\@aspnet\signalr\dist\browser folder. という名前の新しいフォルダーを作成するsignalr下、 wwwroot\libフォルダー。Create a new folder named signalr under the wwwroot\lib folder. コピー、 signalr.jsファイルをwwwroot\lib\signalrフォルダー。Copy the signalr.js file to the wwwroot\lib\signalr folder.

SignalR JavaScript クライアントを使用します。Use the SignalR JavaScript client

SignalR JavaScript クライアントでの参照、<script>要素。Reference the SignalR JavaScript client in the <script> element.

<script src="~/lib/signalr/signalr.js"></script>

ハブへの接続します。Connect to a hub

次のコードでは、作成し、接続を開始します。The following code creates and starts a connection. ハブの名前は大文字小文字を区別します。The hub's name is case insensitive.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

connection.start().then(function () {
    console.log("connected");
});

クロス オリジンの接続Cross-origin connections

通常、ブラウザーでは、要求されたページと同じドメインから接続を読み込みます。Typically, browsers load connections from the same domain as the requested page. ただし、状況が別のドメインへの接続が必要な場合があります。However, there are occasions when a connection to another domain is required.

悪意のあるサイトが別のサイトから機密データを読み取ることを防ぐためにクロス オリジン接続は既定で無効になります。To prevent a malicious site from reading sensitive data from another site, cross-origin connections are disabled by default. クロス オリジン要求を許可することで有効にする、Startupクラス。To allow a cross-origin request, enable it in the Startup class.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SignalRChat.Hubs;

namespace SignalRChat
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddMvc();

            services.AddCors(options => options.AddPolicy("CorsPolicy", 
            builder => 
            {
                builder.AllowAnyMethod().AllowAnyHeader()
                       .WithOrigins("http://localhost:55830")
                       .AllowCredentials();
            }));

            services.AddSignalR();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseCors("CorsPolicy");
            app.UseSignalR(routes => 
            {
                routes.MapHub<ChatHub>("/chathub");
            });
            app.UseMvc();            
        }
    }
}

クライアントからのハブ メソッドの呼び出しCall hub methods from client

JavaScript クライアントは、ハブ経由でのパブリック メソッドを呼び出して、呼び出すのメソッド、 HubConnectionします。JavaScript clients call public methods on hubs via the invoke method of the HubConnection. invokeメソッドは 2 つの引数を受け取ります。The invoke method accepts two arguments:

  • ハブ メソッドの名前。The name of the hub method. 次の例では、ハブのメソッド名はSendMessageします。In the following example, the method name on the hub is SendMessage.

  • ハブ メソッドで定義されている引数。Any arguments defined in the hub method. 次の例では引数名はmessageします。In the following example, the argument name is message. コード例では、現在のバージョンの Internet Explorer を除くすべての主要ブラウザーでサポートされている矢印関数の構文を使用します。The example code uses arrow function syntax that is supported in current versions of all major browsers except Internet Explorer.

    connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
    

注意

Azure SignalR サービスを使用している場合サーバーレス モード、クライアントからハブ メソッドを呼び出すことはできません。If you're using Azure SignalR Service in Serverless mode, you cannot call hub methods from a client. 詳細については、次を参照してください。、 SignalR サービスのドキュメントします。For more information, see the SignalR Service documentation.

invokeメソッドは、JavaScript を返しますPromiseします。The invoke method returns a JavaScript Promise. Promise解決戻り値 (ある場合) サーバー上のメソッドが返されます。The Promise is resolved with the return value (if any) when the method on the server returns. サーバー上のメソッドが、エラーをスローした場合、Promiseと、エラー メッセージは拒否されます。If the method on the server throws an error, the Promise is rejected with the error message. 使用して、thencatchメソッド、Promise自体と、このような場合を処理するために (またはawait構文)。Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

sendメソッドは、JavaScript を返しますPromiseします。The send method returns a JavaScript Promise. Promiseサーバーに、メッセージが送信されたときに解決されます。The Promise is resolved when the message has been sent to the server. メッセージを送信中にエラーがある場合、Promiseと、エラー メッセージは拒否されます。If there is an error sending the message, the Promise is rejected with the error message. 使用して、thencatchメソッド、Promise自体と、このような場合を処理するために (またはawait構文)。Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

注意

使用してsendサーバーがメッセージを受信するまで待機しません。Using send doesn't wait until the server has received the message. その結果、サーバーからデータまたはエラーを返すことはできません。Consequently, it's not possible to return data or errors from the server.

ハブからのクライアント メソッドを呼び出すCall client methods from hub

ハブからメッセージを受信する定義を使用して、メソッド、のメソッド、HubConnectionします。To receive messages from the hub, define a method using the on method of the HubConnection.

  • JavaScript クライアント メソッドの名前。The name of the JavaScript client method. 次の例では、メソッド名はReceiveMessageします。In the following example, the method name is ReceiveMessage.
  • 引数は、hub は、メソッドに渡します。Arguments the hub passes to the method. 引数の値は、次の例では、messageします。In the following example, the argument value is message.
connection.on("ReceiveMessage", (user, message) => {
    const encodedMsg = user + " says " + message;
    const li = document.createElement("li");
    li.textContent = encodedMsg;
    document.getElementById("messagesList").appendChild(li);
});

上記のコードでconnection.onを使用してサーバー側コードから呼び出すときに実行される、 SendAsyncメソッド。The preceding code in connection.on runs when server-side code calls it using the SendAsync method.

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user, message);
}

SignalR を呼び出すメソッド名を照合することによってクライアントの方法を指定してで定義されている引数SendAsyncconnection.onします。SignalR determines which client method to call by matching the method name and arguments defined in SendAsync and connection.on.

注意

ベスト プラクティスを呼び出して、開始メソッドをHubConnectiononします。As a best practice, call the start method on the HubConnection after on. これにより、すべてのメッセージを受信する前に、ハンドラーが登録されます。Doing so ensures your handlers are registered before any messages are received.

エラー処理とログ記録Error handling and logging

チェーンをcatchメソッドの末尾に、startクライアント側のエラーを処理するメソッド。Chain a catch method to the end of the start method to handle client-side errors. 使用console.errorブラウザーのコンソールにエラーを出力します。Use console.error to output errors to the browser's console.

connection.start().catch(function (err) {
    return console.error(err.toString());
});

接続が行われたときにログに記録するには、logger とイベントの種類を渡すことによって、クライアント側のログ トレースをセットアップします。Setup client-side log tracing by passing a logger and type of event to log when the connection is made. 指定されたログ レベル以降、メッセージが記録されます。Messages are logged with the specified log level and higher. 使用可能なログ レベルは次のとおりです。Available log levels are as follows:

  • signalR.LogLevel.Error – エラー メッセージ。signalR.LogLevel.Error – Error messages. ログErrorメッセージのみです。Logs Error messages only.
  • signalR.LogLevel.Warning – 可能性のあるエラーについての警告メッセージ。signalR.LogLevel.Warning – Warning messages about potential errors. ログWarning、およびErrorメッセージ。Logs Warning, and Error messages.
  • signalR.LogLevel.Information – ステータス メッセージがエラーなし。signalR.LogLevel.Information – Status messages without errors. ログInformationWarning、およびErrorメッセージ。Logs Information, Warning, and Error messages.
  • signalR.LogLevel.Trace – メッセージをトレースします。signalR.LogLevel.Trace – Trace messages. ハブとクライアント間で転送されるデータを含め、すべてログに記録します。Logs everything, including data transported between hub and client.

使用して、 configureLoggingメソッドHubConnectionBuilderログ レベルを構成します。Use the configureLogging method on HubConnectionBuilder to configure the log level. メッセージは、ブラウザーのコンソールに記録されます。Messages are logged to the browser console.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

クライアントを再接続します。Reconnect clients

自動的に再接続します。Automatically reconnect

使用して再接続が自動的に SignalR JavaScript クライアントを構成することができます、withAutomaticReconnectメソッドHubConnectionBuilderします。The JavaScript client for SignalR can be configured to automatically reconnect using the withAutomaticReconnect method on HubConnectionBuilder. 既定では、自動的に再接続しません。It won't automatically reconnect by default.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .withAutomaticReconnect()
    .build();

任意のパラメーターを指定せずwithAutomaticReconnect()後、4 つの失敗した試行を停止する各再接続の試行を試す前に、それぞれ 0、2、10、および 30 秒間待機するクライアントを構成します。Without any parameters, withAutomaticReconnect() configures the client to wait 0, 2, 10, and 30 seconds respectively before trying each reconnect attempt, stopping after four failed attempts.

再接続しようとすると、開始する前に、HubConnectionへの移行には、HubConnectionState.Reconnecting起動状態にあり、そのonreconnectingコールバックへの移行ではなく、Disconnected状態とトリガーのoncloseコールバックなどのHubConnectionせず、自動再接続を構成します。Before starting any reconnect attempts, the HubConnection will transition to the HubConnectionState.Reconnecting state and fire its onreconnecting callbacks instead of transitioning to the Disconnected state and triggering its onclose callbacks like a HubConnection without automatic reconnect configured. これは、UI 要素を無効にして、接続が失われたことをユーザーに警告する機会を提供します。This provides an opportunity to warn users that the connection has been lost and to disable UI elements.

connection.onreconnecting((error) => {
  console.assert(connection.state === signalR.HubConnectionState.Reconnecting);

  document.getElementById("messageInput").disabled = true;

  const li = document.createElement("li");
  li.textContent = `Connection lost due to error "${error}". Reconnecting.`;
  document.getElementById("messagesList").appendChild(li);
});

内の最初の 4 つの試行で、クライアントが再接続に成功した場合、HubConnectionから戻るへの移行、Connected起動状態にあり、そのonreconnectedコールバック。If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire its onreconnected callbacks. これは、接続が再確立されたユーザーに通知する機会を提供します。This provides an opportunity to inform users the connection has been reestablished.

接続は、サーバーから完全に新規に見えるため、新しいconnectionIdに提供される、onreconnectedコールバック。Since the connection looks entirely new to the server, a new connectionId will be provided to the onreconnected callback.

警告

onreconnectedコールバックのconnectionIdパラメーターは不確定になる場合、HubConnectionするように構成されたネゴシエーションをスキップします。The onreconnected callback's connectionId parameter will be undefined if the HubConnection was configured to skip negotiation.

connection.onreconnected((connectionId) => {
  console.assert(connection.state === signalR.HubConnectionState.Connected);

  document.getElementById("messageInput").disabled = false;

  const li = document.createElement("li");
  li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`;
  document.getElementById("messagesList").appendChild(li);
});

withAutomaticReconnect() 構成はありません、HubConnection起動障害を手動で処理する必要があるために、初回起動時の障害を再試行します。withAutomaticReconnect() won't configure the HubConnection to retry initial start failures, so start failures need to be handled manually:

async function start() {
    try {
        await connection.start();
        console.assert(connection.state === signalR.HubConnectionState.Connected);
        console.log("connected");
    } catch (err) {
        console.assert(connection.state === signalR.HubConnectionState.Disconnected);
        console.log(err);
        setTimeout(() => start(), 5000);
    }
};

内の最初の 4 つの試行で、クライアントが再接続が正常に場合、HubConnectionへの移行には、Disconnected起動状態にあり、そのoncloseコールバック。If the client doesn't successfully reconnect within its first four attempts, the HubConnection will transition to the Disconnected state and fire its onclose callbacks. これは、接続が完全に失われ、ページの更新をお勧めします。 ユーザーに通知する機会を提供します。This provides an opportunity to inform users the connection has been permanently lost and recommend refreshing the page:

connection.onclose((error) => {
  console.assert(connection.state === signalR.HubConnectionState.Disconnected);

  document.getElementById("messageInput").disabled = true;

  const li = document.createElement("li");
  li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the connection.`;
  document.getElementById("messagesList").appendChild(li);
})

切断する前に再接続試行のカスタムの数を構成または再接続のタイミングを変更するにはwithAutomaticReconnect再接続が試みられるたびに開始する前に待機するミリ秒の遅延を表す数値の配列を受け入れます。In order to configure a custom number of reconnect attempts before disconnecting or change the reconnect timing, withAutomaticReconnect accepts an array of numbers representing the delay in milliseconds to wait before starting each reconnect attempt.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .withAutomaticReconnect([0, 0, 10000])
    .build();

    // .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

上記の例では、HubConnection接続が失われた後にすぐに再接続しようとすると開始します。The preceding example configures the HubConnection to start attempting reconnects immediately after the connection is lost. またこれは、既定の構成に当てはまります。This is also true for the default configuration.

既定の構成でこれと同じように、2 秒待機しているのではなく、最初の再接続試行が失敗すると、2 回目の再接続試行がすぐに開始もは。If the first reconnect attempt fails, the second reconnect attempt will also start immediately instead of waiting 2 seconds like it would in the default configuration.

2 回目の再接続の試行が失敗した場合、これは、既定の構成と同様にもう一度、10 秒後に、3 番目の再接続の試行が開始されます。If the second reconnect attempt fails, the third reconnect attempt will start in 10 seconds which is again like the default configuration.

カスタム動作し、もう一度ブロックから分化既定の動作を停止して 3 番目の再接続試行のいずれかの代わりに失敗した後は別の 30 秒後、既定の構成のように試行を再接続します。The custom behavior then diverges again from the default behavior by stopping after the third reconnect attempt failure instead of trying one more reconnect attempt in another 30 seconds like it would in the default configuration.

タイミングと自動の数をさらに多くのコントロールの接続試行、ならwithAutomaticReconnect実装するオブジェクトを受け入れる、IReconnectPolicyインターフェイスという単一のメソッドをnextRetryDelayInMillisecondsします。If you want even more control over the timing and number of automatic reconnect attempts, withAutomaticReconnect accepts an object implementing the IReconnectPolicy interface, which has a single method named nextRetryDelayInMilliseconds.

nextRetryDelayInMilliseconds 2 つの引数を受け取りpreviousRetryCountelapsedMilliseconds、両方の数値であります。nextRetryDelayInMilliseconds takes two arguments, previousRetryCount and elapsedMilliseconds, which are both numbers. 最初の再接続試行する前に両方previousRetryCountelapsedMillisecondsは 0 になります。Before the first reconnect attempt, both previousRetryCount and elapsedMilliseconds will be zero. 各障害が発生した再試行後previousRetryCount1 つずつ増えますとelapsedMillisecondsはこれまでに再接続するミリ秒単位で費やされた時間数を反映するように更新されます。After each failed retry attempt, previousRetryCount will be incremented by one and elapsedMilliseconds will be updated to reflect the amount of time spent reconnecting so far in milliseconds.

nextRetryDelayInMilliseconds いずれかを表す数値ミリ秒数、[次へ] の再接続の試行までの待機を返す必要がありますまたはnull場合、HubConnection再接続を停止する必要があります。nextRetryDelayInMilliseconds must return either a number representing the number of milliseconds to wait before the next reconnect attempt or null if the HubConnection should stop reconnecting.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .withAutomaticReconnect({
        nextRetryDelayInMilliseconds: (previousRetryCount, elapsedMilliseconds) => {
          if (elapsedMilliseconds < 60000) {
            // If we've been reconnecting for less than 60 seconds so far,
            // wait between 0 and 10 seconds before the next reconnect attempt.
            return Math.random() * 10000;
          } else {
            // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
            return null;
          }
        })
    .build();

再接続で示すように手動で、クライアント コードを記述する代わりに、手動で再接続します。Alternatively, you can write code that will reconnect your client manually as demonstrated in Manually reconnect.

手動での再接続します。Manually reconnect

警告

3.0 では、前に SignalR JavaScript クライアントは自動的に再接続しません。Prior to 3.0, the JavaScript client for SignalR doesn't automatically reconnect. クライアントを手動で再接続するコードを記述する必要があります。You must write code that will reconnect your client manually.

次のコードでは、手動による再接続の一般的なアプローチを示します。The following code demonstrates a typical manual reconnection approach:

  1. 関数 (ここで、start関数)、接続を開始するが作成されます。A function (in this case, the start function) is created to start the connection.
  2. 呼び出す、start関数で、接続のoncloseイベント ハンドラー。Call the start function in the connection's onclose event handler.
async function start() {
    try {
        await connection.start();
        console.log("connected");
    } catch (err) {
        console.log(err);
        setTimeout(() => start(), 5000);
    }
};

connection.onclose(async () => {
    await start();
});

実際の実装は、指数バックオフを使用して、または断念する前に指定された回数を再試行してください。A real-world implementation would use an exponential back-off or retry a specified number of times before giving up.

その他の技術情報Additional resources