繼續學習
最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)為小程序提供websocket支持,前端時間也發了一個學習筆記,在使用過程中稍微看了下它的源碼,不得不說微軟現在真的強大,很多事情都幫你考慮到了,比如使用Redis,使用Redis后,你的websocket就支持橫向擴展了,使用的方式也特別簡單,只需要在services.AddSignalR
的后面再加上:
.AddRedis(options =>
{
options.Configuration.ConnectTimeout = 30;
options.Configuration.EndPoints.Add("redis ip");
})
SignalR Core利用了Redis的發布訂閱功能,就實現了橫向擴展,再也不用擔心一台ws服務器不夠用了.
今天要說的並不是SignalR Core的負載均衡方式,而是如何優雅的調用前端方法。大家都知道SignalR Core除了可以建立websocket連接,還能雙向調用,服務器調用客戶端方法,客戶端也能調用服務器的方法。
原始調用
我們看下如何調用客戶端方法:
public class ChatHub : Hub
{
//服務端方法
public async Task SendMessage(string user, string message)
{
//ReceiveMessage 為客戶端方法,讓所有客戶端調用這個方法
await Clients.All.SendAsync("sayHello", user, message);
}
}
還是ChatHub~~~~~
我們可以看到在這里我們調用了客戶端的sayHello,並傳遞了兩個字符串參數user,message,是不是覺得丑陋,說實在的真心看不下去哈。而且不變維護,相當於你要把方法名硬編碼,傳遞多少個參數也沒有個准,沒有好的文檔后期很難維護。好在微軟已經為我們考慮到了這個情況,我們可以把客戶端的方法用接口的方法定義了!!!對!沒錯,用接口的方式定義客戶端的方法!!
優雅調用
使用的方式也超級簡單,我們先定義一個客戶端的接口:
public interface IMyClient
{
Task SayHello(string user, string message);
}
然后我們的Hub集成Hub
public class SendMessageHub : Hub<IMyClient>
{
public async Task SendMessage(string user, string message)
{
await this.Clients.All.SayHello(user, "from server:" + message);
//ReceiveMessage 為客戶端方法,讓所有客戶端調用這個方法
//await Clients.All.SendAsync("sayHello", user, message);
}
}
注釋掉的是我之前的方式,SayHello是客戶端的方法,會通過websocket傳遞到前端,下圖為我用小程序通訊產生的結果:
是不是SoEasy??我覺得還不算完,我們參數目前是按照數組的方式傳遞的,如果有限定的參數名就完美了,我們改造下IMyClient:
public interface IMyClient
{
Task SayHello(HelloMessage message);
}
public class HelloMessage
{
public string User { get; set; }
public string Message { get; set; }
}
修改下我們的Hub的SendMessage方法:
public Task SendMessage(string user, string message)
{
return this.Clients.All.SayHello(new HelloMessage()
{
User = user,
Message = "from server:" + message
});
//return this.Clients.All.SendAsync("sayHello", $"from server:{message}");
}
在運行下我們的小程序:
LooK,方法名沒有改變,但是我們返回的參數成了一個對象,如果看過我之前那篇博文的話,應該記得在前端的時候,我需要做一個映射,來調用前端的方法,在映射中,我參數使用的是數組進行傳遞的,現在不需要去看數組中第幾個參數是我需要使用的了,你完全可以使用:
callMethods(methods, args) {
console.log(methods, args);
let self = this;
let arg = args[0];
switch (methods) {
case 'SayHello':
self.sayHello(arg.message);
break;
}
},
這里還有個問題,就是接口中的方法名是大寫開頭的,而js的規范呢一般都是小寫開頭的,所以在映射方法的時候需要注意下,反正這個大小寫問題有點不是很爽,參數在傳遞的時候倒是直接轉換成首字母小寫,我相信SignalR Core是可以實現的,只是我不知道而已,稍后在研究研究,如果可行,我會更新此篇博文。如果你要在接口中用小寫來定義這個方法,也沒有問題,但我覺得就是不符合規范,習慣不允許我如此粗糙,哈哈。
寫在最后
至於調用的原理,我沒有細看,正好在看源碼的時候,看到了Hub
Asp.Net Core SignalR確實很強大,有興趣的可以去gayhub上去研究下他們的源碼。