ASP.NET Core SignalR JavaScript istemcisi
Tarafından Rachel Appel
ASP.NET Core SignalR JavaScript istemci kitaplığı, geliştiricilerin sunucu tarafı SignalR hub kodunu çağırmasına olanak tanır.
SignalR İstemci paketini yükleme
SignalR JavaScript istemci kitaplığı bir npm paketi olarak teslim edilir. Aşağıdaki bölümlerde istemci kitaplığını yüklemenin farklı yolları özetlenmiştir.
npm ile yükleme
Paket Yöneticisi Konsolu'ndan aşağıdaki komutları çalıştırın:
npm init -y
npm install @microsoft/signalr
npm, paket içeriğini node_modules\@microsoft\\signalrdist\browser klasörüne yükler. wwwroot/lib/signalr klasörünü oluşturun. signalr.js
Dosyayı wwwroot/lib/signalr klasörüne kopyalayın.
öğesinde SignalR JavaScript istemcisine <script>
başvurun. Örneğin:
<script src="~/lib/signalr/signalr.js"></script>
Content Delivery Network (CDN) kullanma
İstemci kitaplığını npm önkoşulu olmadan kullanmak için istemci kitaplığının CDN tarafından barındırılan bir kopyasına başvurun. Örneğin:
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
İstemci kitaplığı aşağıdaki CDN'lerde kullanılabilir:
LibMan ile yükleme
LibMan , CDN tarafından barındırılan istemci kitaplığından belirli istemci kitaplığı dosyalarını yüklemek için kullanılabilir. Örneğin, projeye yalnızca küçültüldü JavaScript dosyasını ekleyin. Bu yaklaşımla ilgili ayrıntılar için bkz. İstemci kitaplığınıSignalR ekleme.
Hub'a bağlanma
Aşağıdaki kod bir bağlantı oluşturur ve başlatır. Hub'ın adı büyük/küçük harfe duyarlı değildir:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
// Start the connection.
start();
Çıkış noktaları arası bağlantılar (CORS)
Genellikle, tarayıcılar istenen sayfayla aynı etki alanından bağlantıları yükler. Ancak, başka bir etki alanına bağlantının gerekli olduğu durumlar vardır.
Etki alanları arası isteklerde bulunurken istemci kodunun göreli URL yerine mutlak bir URL kullanması gerekir. Etki alanları arası istekler için olarak .withUrl("https://{App domain name}/chathub")
değiştirin.withUrl("/chathub")
.
Kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önlemek için çıkış noktaları arası bağlantılar varsayılan olarak devre dışı bırakılır. Çıkış noktaları arası bir isteğe izin vermek için CORS'yi etkinleştirin:
using SignalRChat.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("https://example.com")
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
// UseCors must be called before MapHub.
app.UseCors();
app.MapRazorPages();
app.MapHub<ChatHub>("/chatHub");
app.Run();
UseCors çağrılmadan MapHubönce çağrılmalıdır.
İstemciden çağrı hub'ı yöntemleri
JavaScript istemcileri HubConnection'ın invoke yöntemi aracılığıyla hub'larda genel yöntemleri çağırır. invoke
yöntemi aşağıdakileri kabul eder:
- Hub yönteminin adı.
- Hub yönteminde tanımlanan tüm bağımsız değişkenler.
Aşağıdaki vurgulanan kodda, hub'daki yöntem adı şeklindedir SendMessage
. Hub yönteminin user
ve bağımsız değişkenleriyle eşlemek için invoke
geçirilen ikinci ve message
üçüncü bağımsız değişkenler:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
İstemciden hub yöntemlerini çağırmak yalnızca Azure SignalR Hizmeti Varsayılan modda kullanılırken desteklenir. Daha fazla bilgi için bkz . Sık Sorulan Sorular (azure-signalr GitHub deposu).
invoke
yöntemi bir JavaScript Promise
döndürür. Promise
, sunucudaki yöntem döndürdüğünde dönüş değeriyle (varsa) çözümlenir. Sunucudaki yöntem bir hata oluşturursa, Promise
hata iletisiyle reddedilir. Bu durumları işlemek için ve await
veya then
Promise
ve catch
yöntemlerini kullanınasync
.
JavaScript istemcileri, gönderme yöntemi aracılığıyla hub'larda genel yöntemleri HubConnection
de çağırabilir. yönteminden invoke
farklı olarak send
, yöntemi sunucudan yanıt beklemez. send
yöntemi bir JavaScript Promise
döndürür. , Promise
ileti sunucuya gönderildiğinde çözülür. İleti gönderilirken bir hata varsa, Promise
hata iletisiyle reddedilir. Bu durumları işlemek için ve await
veya then
Promise
ve catch
yöntemlerini kullanınasync
.
kullanmak send
, sunucu iletiyi alana kadar beklemez . Sonuç olarak, sunucudan veri veya hata döndürmek mümkün değildir.
Hub'dan istemci yöntemlerini çağırma
Hub'dan ileti almak için on yöntemini kullanarak bir yöntem HubConnection
tanımlayın.
- JavaScript istemci yönteminin adı.
- Hub'ın yöntemine geçirdiği bağımsız değişkenler.
Aşağıdaki örnekte yöntem adı şeklindedir ReceiveMessage
. Bağımsız değişken adları şunlardıruser
:message
connection.on("ReceiveMessage", (user, message) => {
const li = document.createElement("li");
li.textContent = `${user}: ${message}`;
document.getElementById("messageList").appendChild(li);
});
içindeki connection.on
önceki kod, sunucu tarafı kodu yöntemini kullanarak SendAsync çağırdığında çalışır:
using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
SignalRve connection.on
içinde SendAsync
tanımlanan yöntem adı ve bağımsız değişkenleriyle eşleşerek hangi istemci yönteminin çağrıldığını belirler.
En iyi yöntem, sonrasında on
başlangıç yöntemini çağırmaktırHubConnection
. Bunun yapılması, herhangi bir ileti alınmadan önce işleyicilerin kaydedilmesini sağlar.
Hata işleme ve günlüğe kaydetme
İstemci bağlanamaz veya ileti gönderemezse tarayıcının konsoluna hata çıkarmak için kullanın console.error
:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Bağlantı kurulurken günlüğe kaydedilecek bir günlükçü ve olay türünü geçirerek istemci tarafı günlük izlemesini ayarlayın. İletiler belirtilen günlük düzeyinde ve daha yüksek bir değerle günlüğe kaydedilir. Kullanılabilir günlük düzeyleri aşağıdaki gibidir:
signalR.LogLevel.Error
: Hata iletileri. Yalnızca iletileri günlüğe kaydederError
.signalR.LogLevel.Warning
: Olası hatalar hakkında uyarı iletileri.Error
ve iletilerini günlüğe kaydederWarning
.signalR.LogLevel.Information
: Hatasız durum iletileri. ,Warning
veError
iletilerini günlüğe kaydederInformation
.signalR.LogLevel.Trace
: İletileri izleme. Hub ile istemci arasında taşınan veriler de dahil olmak üzere her şeyi günlüğe kaydeder.
Günlük düzeyini yapılandırmak için HubConnectionBuilder'da configureLogging yöntemini kullanın. İletiler tarayıcı konsoluna kaydedilir:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
İstemcileri yeniden bağlama
Otomatik olarak yeniden bağlanma
için SignalR JavaScript istemcisi, HubConnectionBuilder'da WithAutomaticReconnect yöntemi kullanılarak otomatik olarak yeniden bağlanacak şekilde yapılandırılabilir. Varsayılan olarak otomatik olarak yeniden bağlanmaz.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Herhangi bir parametre olmadan, WithAutomaticReconnect her yeniden bağlanma girişimini denemeden önce istemciyi sırasıyla 0, 2, 10 ve 30 saniye bekleyecek şekilde yapılandırılır. Dört başarısız denemeden sonra yeniden bağlanma denemesi durdurulur.
Yeniden bağlanma girişimlerini başlatmadan önce, :HubConnection
- Duruma geçişler
HubConnectionState.Reconnecting
ve geri çağırmalarını tetikleronreconnecting
. - Duruma geçiş
Disconnected
yapmaz ve otomatik yeniden bağlanma yapılandırılmamış gibiHubConnection
geri çağırmalarını tetikleronclose
.
Yeniden bağlanma yaklaşımı aşağıdakiler için bir fırsat sağlar:
- Bağlantıyı kaybettiği konusunda kullanıcıları uyarın.
- Kullanıcı arabirimi öğelerini devre dışı bırakın.
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("messageList").appendChild(li);
});
İstemci ilk dört denemesinde başarıyla yeniden bağlanırsa, HubConnection
duruma geri Connected
döner ve geri çağrılarını tetikler onreconnected
. Bu, kullanıcılara bağlantının yeniden kuruldığını bildirmek için bir fırsat sağlar.
Bağlantı sunucu için tamamen yeni göründüğünden, geri çağırmaya onreconnected
yeni connectionId
bir sağlanır.
onreconnected
geri çağırmanın connectionId
parametresi, anlaşması atlamak üzere yapılandırıldıysa HubConnection
tanımlanmamıştır.
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("messageList").appendChild(li);
});
withAutomaticReconnect
ilk başlatma hatalarını yeniden denemek için öğesini yapılandırmaz HubConnection
, bu nedenle başlatma hatalarının el ile işlenmesi gerekir:
async function start() {
try {
await connection.start();
console.assert(connection.state === signalR.HubConnectionState.Connected);
console.log("SignalR Connected.");
} catch (err) {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
console.log(err);
setTimeout(() => start(), 5000);
}
};
İstemci ilk dört denemesinde başarıyla yeniden bağlanamazsa, HubConnection
duruma geçişler Disconnected
ve onclose geri çağırmalarını tetikler. Bu, kullanıcıları bilgilendirmek için bir fırsat sağlar:
- Bağlantı kalıcı olarak kesildi.
- Sayfayı yenilemeyi deneyin:
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("messageList").appendChild(li);
});
Bağlantıyı kesmeden veya yeniden bağlanma zamanlamasını değiştirmeden önce özel sayıda yeniden bağlanma girişimi yapılandırmak için, withAutomaticReconnect
her yeniden bağlantı girişimine başlamadan önce beklenmesi gereken gecikmeyi milisaniye cinsinden gösteren bir sayı dizisini kabul eder.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect([0, 0, 10000])
.build();
// .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior
Yukarıdaki örnek, bağlantı kesildikten hemen sonra yeniden bağlanmayı başlatacak şekilde yapılandırılır HubConnection
. Varsayılan yapılandırma yeniden bağlanmayı denemesi için de sıfır saniye bekler.
İlk yeniden bağlanma girişimi başarısız olursa, ikinci yeniden bağlanma girişimi de varsayılan yapılandırmayı kullanarak 2 saniye beklemek yerine hemen başlar.
İkinci yeniden bağlanma girişimi başarısız olursa, üçüncü yeniden bağlanma girişimi varsayılan yapılandırmayla aynı olan 10 saniye içinde başlar.
Yapılandırılan yeniden bağlantı zamanlaması, 30 saniye içinde bir yeniden bağlantı denemesi daha denemek yerine üçüncü yeniden bağlantı girişimi hatasından sonra durdurularak varsayılan davranıştan farklıdır.
Otomatik yeniden bağlanma girişimlerinin zamanlaması ve sayısı üzerinde daha fazla denetim için, withAutomaticReconnect
adlı nextRetryDelayInMilliseconds
tek bir yöntemi olan arabirimini uygulayan IRetryPolicy
bir nesneyi kabul eder.
nextRetryDelayInMilliseconds
türünde RetryContext
tek bir bağımsız değişken alır. üç RetryContext
özelliğe sahiptir: previousRetryCount
elapsedMilliseconds
ve retryReason
sırasıyla , number
a number
ve şeklindedirError
. İlk yeniden bağlanma girişiminden önce hem hem elapsedMilliseconds
de previousRetryCount
sıfır olur ve retryReason
bağlantının kaybolmasına neden olan Hata olur. Her başarısız yeniden deneme girişiminden sonra bir previousRetryCount
artırılır, elapsedMilliseconds
şimdiye kadar yeniden bağlanmaya harcanan süreyi milisaniye cinsinden yansıtacak şekilde güncelleştirilir ve retryReason
son yeniden bağlanma girişiminin başarısız olmasına neden olan Hata olur.
nextRetryDelayInMilliseconds
bir sonraki yeniden bağlanma girişiminden önce beklenmesi gereken milisaniye sayısını veya null
yeniden bağlanmayı durdurması HubConnection
gerektiğini gösteren bir sayı döndürmelidir.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.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();
Alternatif olarak, aşağıdaki bölümde gösterildiği gibi istemciyi el ile yeniden bağlayan kod yazılabilir.
El ile yeniden bağlanma
Aşağıdaki kod tipik bir el ile yeniden bağlanma yaklaşımını gösterir:
- Bağlantıyı başlatmak için bir işlev (bu durumda
start
işlev) oluşturulur. - Bağlantının
start
olay işleyicisinde işlevini çağırınonclose
.
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
Üretim uygulamaları genellikle üstel bir geri çekilme kullanır veya belirtilen sayıda yeniden dener.
Tarayıcı uyku sekmesi
Bazı tarayıcılarda, etkin olmayan sekmeler için bilgisayar kaynağı kullanımını azaltmak için sekme dondurma veya uyku özelliği vardır. Bu, bağlantıların kapanmasına neden SignalR olabilir ve istenmeyen bir kullanıcı deneyimine neden olabilir. Tarayıcılar, aşağıdakiler gibi bir sekmenin uyku moduna alınması gerekip gerekmediğini bulmak için buluşsal yöntemler kullanır:
- Ses çalma
- Web kilidi tutma
- Kilit tutma
IndexedDB
- USB cihazına bağlı olma
- Video veya ses yakalama
- Yansıtılıyor
- Pencere veya ekran yakalama
Tarayıcı buluşsal yöntemleri zaman içinde değişebilir ve tarayıcılar arasında farklılık gösterebilir. Destek matrisini gözden geçirin ve senaryolarınız için en uygun yöntemin hangisi olduğunu öğrenin.
Bir uygulamayı uyku moduna almaktan kaçınmak için, uygulamanın tarayıcının kullandığı buluşsal yöntemlerden birini tetiklemesi gerekir.
Aşağıdaki kod örneğinde, bir sekmeyi uyanık tutmak ve beklenmeyen bir bağlantının kapatılmasını önlemek için Web Kilidi'nin nasıl kullanılacağı gösterilmektedir.
var lockResolver;
if (navigator && navigator.locks && navigator.locks.request) {
const promise = new Promise((res) => {
lockResolver = res;
});
navigator.locks.request('unique_lock_name', { mode: "shared" }, () => {
return promise;
});
}
Yukarıdaki kod örneği için:
- Web Kilitleri deneyseldir. Koşullu denetim, tarayıcının Web Kilitleri'ni desteklediğini onaylar.
- Promise çözümleyicisi,
lockResolver
sekmenin uyku moduna alınması kabul edilebilir olduğunda kilidin serbest bırakılabilmesi için depolanır. - Bağlantı kapatılırken kilit çağrılarak
lockResolver()
serbest bırakılır. Kilit serbest bırakıldığında sekmenin uyku moduna girmesine izin verilir.
Ek kaynaklar
Tarafından Rachel Appel
ASP.NET Core SignalR JavaScript istemci kitaplığı, geliştiricilerin sunucu tarafı hub kodunu çağırmasına olanak tanır.
Örnek kodu görüntüleme veya indirme (indirme)
SignalR İstemci paketini yükleme
SignalR JavaScript istemci kitaplığı bir npm paketi olarak teslim edilir. Aşağıdaki bölümlerde istemci kitaplığını yüklemenin farklı yolları özetlenmiştir.
npm ile yükleme
Visual Studio için, kök klasördeyken Paket Yöneticisi Konsolu'ndan aşağıdaki komutları çalıştırın. Visual Studio Code için, Tümleşik Terminal'den aşağıdaki komutları çalıştırın.
npm init -y
npm install @microsoft/signalr
npm, paket içeriğini node_modules\@microsoft\\signalrdist\browser klasörüne yükler. wwwroot\lib klasörünün altında adlı signalr yeni bir klasör oluşturun. signalr.js
Dosyayı wwwroot\lib\signalr klasörüne kopyalayın.
öğesinde SignalR JavaScript istemcisine <script>
başvurun. Örneğin:
<script src="~/lib/signalr/signalr.js"></script>
Content Delivery Network (CDN) kullanma
İstemci kitaplığını npm önkoşulu olmadan kullanmak için istemci kitaplığının CDN tarafından barındırılan bir kopyasına başvurun. Örneğin:
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.js"></script>
İstemci kitaplığı aşağıdaki CDN'lerde kullanılabilir:
LibMan ile yükleme
LibMan , CDN tarafından barındırılan istemci kitaplığından belirli istemci kitaplığı dosyalarını yüklemek için kullanılabilir. Örneğin, projeye yalnızca küçültüldü JavaScript dosyasını ekleyin. Bu yaklaşımla ilgili ayrıntılar için bkz. İstemci kitaplığınıSignalR ekleme.
Hub'a bağlanma
Aşağıdaki kod bir bağlantı oluşturur ve başlatır. Hub'ın adı büyük/küçük harfe duyarlı değildir:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
// Start the connection.
start();
Çıkış noktaları arası bağlantılar
Genellikle, tarayıcılar istenen sayfayla aynı etki alanından bağlantıları yükler. Ancak, başka bir etki alanına bağlantının gerekli olduğu durumlar vardır.
Önemli
İstemci kodu göreli URL yerine mutlak BIR URL kullanmalıdır. .withUrl("/chathub")
değerini .withUrl("https://myappurl/chathub")
olarak değiştirin.
Kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önlemek için çıkış noktaları arası bağlantılar varsayılan olarak devre dışı bırakılır. Çıkış noktaları arası bir isteğe izin vermek için bunu sınıfında etkinleştirin Startup
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;
namespace SignalRChat
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSignalR();
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins("https://example.com")
.AllowCredentials();
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chathub");
});
}
}
}
İstemciden çağrı hub'ı yöntemleri
JavaScript istemcileri HubConnection'ın invoke yöntemi aracılığıyla hub'larda genel yöntemleri çağırır. invoke
yöntemi aşağıdakileri kabul eder:
- Hub yönteminin adı.
- Hub yönteminde tanımlanan tüm bağımsız değişkenler.
Aşağıdaki örnekte, hub'daki yöntem adı şeklindedir SendMessage
. Hub yönteminin user
ve bağımsız değişkenleriyle eşlemek için invoke
geçirilen ikinci ve message
üçüncü bağımsız değişkenler:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Not
İstemciden hub yöntemlerini çağırmak yalnızca Azure SignalR Hizmeti Varsayılan modda kullanılırken desteklenir. Daha fazla bilgi için bkz . Sık Sorulan Sorular (azure-signalr GitHub deposu).
invoke
yöntemi bir JavaScript Promise
döndürür. Promise
, sunucudaki yöntem döndürdüğünde dönüş değeriyle (varsa) çözümlenir. Sunucudaki yöntem bir hata oluşturursa, Promise
hata iletisiyle reddedilir. Bu durumları işlemek için ve await
veya then
Promise
ve catch
yöntemlerini kullanınasync
.
JavaScript istemcileri, gönderme yöntemi aracılığıyla hub'larda genel yöntemleri HubConnection
de çağırabilir. yönteminden invoke
farklı olarak send
, yöntemi sunucudan yanıt beklemez. send
yöntemi bir JavaScript Promise
döndürür. , Promise
ileti sunucuya gönderildiğinde çözülür. İleti gönderilirken bir hata varsa, Promise
hata iletisiyle reddedilir. Bu durumları işlemek için ve await
veya then
Promise
ve catch
yöntemlerini kullanınasync
.
Not
kullanmak send
, sunucu iletiyi alana kadar beklemez. Sonuç olarak, sunucudan veri veya hata döndürmek mümkün değildir.
Hub'dan istemci yöntemlerini çağırma
Hub'dan ileti almak için on yöntemini kullanarak bir yöntem HubConnection
tanımlayın.
- JavaScript istemci yönteminin adı.
- Hub'ın yöntemine geçirdiği bağımsız değişkenler.
Aşağıdaki örnekte yöntem adı şeklindedir ReceiveMessage
. Bağımsız değişken adları şunlardıruser
:message
connection.on("ReceiveMessage", (user, message) => {
const li = document.createElement("li");
li.textContent = `${user}: ${message}`;
document.getElementById("messageList").appendChild(li);
});
içindeki connection.on
önceki kod, sunucu tarafı kodu yöntemini kullanarak SendAsync çağırdığında çalışır:
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
SignalRve connection.on
içinde SendAsync
tanımlanan yöntem adı ve bağımsız değişkenleriyle eşleşerek hangi istemci yönteminin çağrıldığını belirler.
Not
En iyi uygulama olarak, sonrasında üzerinde başlangıç yöntemini çağırın HubConnection
.on
Bunun yapılması, herhangi bir ileti alınmadan önce işleyicilerinizin kaydedilmesini sağlar.
Hata işleme ve günlüğe kaydetme
catch
İstemci tarafı hatalarını işlemek için ve await
ile async
veya catch
Promise
ile yöntemini kullanıntry
. Tarayıcının konsolunda hata çıktısı almak için kullanın console.error
:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Bağlantı kurulurken günlüğe kaydedilecek bir günlükçü ve olay türünü geçirerek istemci tarafı günlük izlemesini ayarlayın. İletiler belirtilen günlük düzeyinde ve daha yüksek bir değerle günlüğe kaydedilir. Kullanılabilir günlük düzeyleri aşağıdaki gibidir:
signalR.LogLevel.Error
: Hata iletileri. Yalnızca iletileri günlüğe kaydederError
.signalR.LogLevel.Warning
: Olası hatalar hakkında uyarı iletileri.Error
ve iletilerini günlüğe kaydederWarning
.signalR.LogLevel.Information
: Hatasız durum iletileri. ,Warning
veError
iletilerini günlüğe kaydederInformation
.signalR.LogLevel.Trace
: İletileri izleme. Hub ile istemci arasında taşınan veriler de dahil olmak üzere her şeyi günlüğe kaydeder.
Günlük düzeyini yapılandırmak için HubConnectionBuilder'da configureLogging yöntemini kullanın. İletiler tarayıcı konsoluna kaydedilir:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
İstemcileri yeniden bağlama
Otomatik olarak yeniden bağlanma
için SignalR JavaScript istemcisi, HubConnectionBuilder'da yöntemi kullanılarak withAutomaticReconnect
otomatik olarak yeniden bağlanacak şekilde yapılandırılabilir. Varsayılan olarak otomatik olarak yeniden bağlanmaz.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Herhangi bir parametre olmadan, withAutomaticReconnect()
istemciyi her yeniden bağlanma girişimini denemeden önce sırasıyla 0, 2, 10 ve 30 saniye bekleyecek şekilde yapılandırarak başarısız olan dört denemeden sonra durdurulmasını sağlar.
Yeniden bağlanma girişimlerine başlamadan önce, HubConnection
duruma onreconnecting
geçiş HubConnectionState.Reconnecting
ve otomatik yeniden bağlanma yapılandırılmamış gibi HubConnection
geri çağırmalarını tetikleme onclose
yerine Disconnected
duruma geçiş ve geri çağırmaları tetikler. Bu, kullanıcıları bağlantının kaybolduğu konusunda uyarmak ve kullanıcı arabirimi öğelerini devre dışı bırakmak için bir fırsat sağlar.
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("messageList").appendChild(li);
});
İstemci ilk dört denemesinde başarıyla yeniden bağlanırsa, HubConnection
duruma geri Connected
döner ve geri çağrılarını tetikler onreconnected
. Bu, kullanıcılara bağlantının yeniden kuruldığını bildirmek için bir fırsat sağlar.
Bağlantı sunucu için tamamen yeni göründüğünden, geri çağırmaya onreconnected
yeni connectionId
bir sağlanacaktır.
Uyarı
onreconnected
geri çağırma connectionId
parametresi, anlaşma atlayacak şekilde yapılandırıldıysa HubConnection
tanımlanmamış olur.
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("messageList").appendChild(li);
});
withAutomaticReconnect()
ilk başlatma hatalarını yeniden denemek için öğesini yapılandırmaz HubConnection
, bu nedenle başlatma hatalarının el ile işlenmesi gerekir:
async function start() {
try {
await connection.start();
console.assert(connection.state === signalR.HubConnectionState.Connected);
console.log("SignalR Connected.");
} catch (err) {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
console.log(err);
setTimeout(() => start(), 5000);
}
};
İstemci ilk dört denemesinde başarılı bir şekilde yeniden bağlanamazsa, duruma geçirilecek Disconnected
ve onclose geri çağırmalarını tetikleyecektir.HubConnection
Bu, kullanıcılara bağlantının kalıcı olarak kaybolduğunu bildirmek ve sayfayı yenilemeyi önermek için bir fırsat sağlar:
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("messageList").appendChild(li);
});
Bağlantıyı kesmeden veya yeniden bağlanma zamanlamasını değiştirmeden önce özel sayıda yeniden bağlanma girişimi yapılandırmak için, withAutomaticReconnect
her yeniden bağlantı girişimine başlamadan önce beklenmesi gereken gecikmeyi milisaniye cinsinden gösteren bir sayı dizisini kabul eder.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect([0, 0, 10000])
.build();
// .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior
Yukarıdaki örnek, bağlantı kesildikten hemen sonra yeniden bağlanmayı başlatacak şekilde yapılandırılır HubConnection
. Bu, varsayılan yapılandırma için de geçerlidir.
İlk yeniden bağlanma girişimi başarısız olursa, ikinci yeniden bağlanma girişimi de varsayılan yapılandırmada olduğu gibi 2 saniye beklemek yerine hemen başlar.
İkinci yeniden bağlanma girişimi başarısız olursa, üçüncü yeniden bağlanma girişimi 10 saniye içinde başlar ve bu yeniden varsayılan yapılandırmaya benzer.
Daha sonra özel davranış, varsayılan yapılandırmada olduğu gibi 30 saniye içinde bir yeniden bağlanma denemesi daha denemek yerine üçüncü yeniden bağlanma girişimi hatasından sonra durarak varsayılan davranıştan yeniden ayrılır.
Otomatik yeniden bağlanma girişimlerinin zamanlaması ve sayısı üzerinde daha fazla denetime sahip olmak istiyorsanız, withAutomaticReconnect
adlı nextRetryDelayInMilliseconds
tek bir yöntemi olan arabirimi uygulayan IRetryPolicy
bir nesneyi kabul eder.
nextRetryDelayInMilliseconds
türünde RetryContext
tek bir bağımsız değişken alır. üç RetryContext
özelliğe sahiptir: previousRetryCount
elapsedMilliseconds
ve retryReason
sırasıyla , number
a number
ve şeklindedirError
. İlk yeniden bağlanma girişiminden önce hem hem elapsedMilliseconds
de previousRetryCount
sıfır olur ve retryReason
bağlantının kaybolmasına neden olan Hata olur. Her başarısız yeniden deneme girişiminden sonra bir previousRetryCount
artırılır, elapsedMilliseconds
şimdiye kadar yeniden bağlanmaya harcanan süreyi milisaniye cinsinden yansıtacak şekilde güncelleştirilir ve retryReason
son yeniden bağlanma girişiminin başarısız olmasına neden olan Hata olur.
nextRetryDelayInMilliseconds
bir sonraki yeniden bağlanma girişiminden önce beklenmesi gereken milisaniye sayısını veya null
yeniden bağlanmayı durdurması HubConnection
gerektiğini gösteren bir sayı döndürmelidir.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.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();
Alternatif olarak, el ile yeniden bağlanma bölümünde gösterildiği gibi istemcinizi el ile yeniden bağlayacak kod yazabilirsiniz.
El ile yeniden bağlanma
Aşağıdaki kod tipik bir el ile yeniden bağlanma yaklaşımını gösterir:
- Bağlantıyı başlatmak için bir işlev (bu durumda
start
işlev) oluşturulur. - Bağlantının
start
olay işleyicisinde işlevini çağırınonclose
.
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
Üretim uygulamaları genellikle üstel bir geri çekilme kullanır veya belirtilen sayıda yeniden dener.
Tarayıcı uyku sekmesi
Bazı tarayıcılarda, etkin olmayan sekmeler için bilgisayar kaynağı kullanımını azaltmak için sekme dondurma veya uyku özelliği vardır. Bu, bağlantıların kapanmasına neden SignalR olabilir ve istenmeyen bir kullanıcı deneyimine neden olabilir. Tarayıcılar, aşağıdakiler gibi bir sekmenin uyku moduna alınması gerekip gerekmediğini bulmak için buluşsal yöntemler kullanır:
- Ses çalma
- Web kilidi tutma
- Kilit tutma
IndexedDB
- USB cihazına bağlı olma
- Video veya ses yakalama
- Yansıtılıyor
- Pencere veya ekran yakalama
Not
Bu buluşsal yöntemler zaman içinde değişebilir veya tarayıcılar arasında farklılık gösterebilir. Destek matrisinizi denetleyin ve senaryolarınız için en uygun yöntemin hangisi olduğunu öğrenin.
Bir uygulamayı uyku moduna almaktan kaçınmak için, uygulamanın tarayıcının kullandığı buluşsal yöntemlerden birini tetiklemesi gerekir.
Aşağıdaki kod örneğinde, bir sekmeyi uyanık tutmak ve beklenmeyen bir bağlantının kapatılmasını önlemek için Web Kilidi'nin nasıl kullanılacağı gösterilmektedir.
var lockResolver;
if (navigator && navigator.locks && navigator.locks.request) {
const promise = new Promise((res) => {
lockResolver = res;
});
navigator.locks.request('unique_lock_name', { mode: "shared" }, () => {
return promise;
});
}
Yukarıdaki kod örneği için:
- Web Kilitleri deneyseldir. Koşullu denetim, tarayıcının Web Kilitleri'ni desteklediğini onaylar.
- Promise çözümleyicisi (
lockResolver
), sekmenin uyku moduna alınması kabul edilebilir olduğunda kilidin serbest bırakılabilmesi için depolanır. - Bağlantı kapatılırken kilit çağrılarak
lockResolver()
serbest bırakılır. Kilit serbest bırakıldığında sekmenin uyku moduna girmesine izin verilir.
Ek kaynaklar
ASP.NET Core