Bài viết được sự cho phép của tác giả Phạm Công Sơn
Tôi chia sẻ kinh nghiệm và thư viện mở rộng mà tôi viết để kết nối tới Hub sử dụng SignalR. Thư viện do tôi mở rộng thêm với mục đích
- 1. Có thể kết nối được tới nhiều Hub
- 2. Duy trì được kết nối ổn định: Khi
disconnected
thì sẽ tự động kết nối trở lại - 3. Có thể đăng ký nhiều sự kiện để nhận data được push từ server gửi về
- 4. Khi gửi request lên server Hub thì chỉ gửi được khi đang ở trạng thái kết nối tốt.
Để tải thư viện mở rộng do tôi viết các bạn có thể tải tại đây.
function
Hub(hubUrl, hubName)
{
this
.onOk =
function
(func) {
if
(state == 2) func(); };
this
.onBeforeStart =
function
() { };
this
.start =
function
() {
/* Code coe */
};
}
Phần mở rộng tôi viết gồm hubUrl
, hubName
là trỏ đến địa chỉ Hub cần kết nối tới. this.onOk
là phương thức đảm bảo đang ở trạng thái kết nối mới thực hiện func
(một hành động nào đó). Với class
Hub tôi đã xử lý hết các sự kiện khi mất kết nối, đang kết nối và kết nối
// Nếu bị mất kết nối thì 2s sau sẽ kết nối lại $this.hub.connection.disconnected(function () { console.log("disconnected"); state = 1; var t = setInterval(function () { $this.doHubStart(true); clearInterval(t); }, $this.timeout); }); $this.hub.connection.reconnecting(function () { state = 1; console.log("reconnecting"); }); // Đã được kết nối lại $this.hub.connection.reconnected(function () { console.log("reconnected"); var t = setInterval(function () { $this.doHubStart(true); clearInterval(t); }, $this.timeout); });
Nếu bị mất kết nối, thì sau khoảng this.timeout
(mặc định 2000ms) sẽ thực hiện kết nối lại.
Hub.ActionRegistry = function () { this.registry = function (func) { /* Code code */ } /* Code Code */ }
Với Hub.ActionRegistry
được dùng để đăng ký các hành động sau khi nhận dữ liệu được push từ server gửi về. Tại sao tôi lại viết class
này, vì tôi hướng tới có thể nhiều nơi, nhiều module mà cũng muốn nhận dữ liệu push về mà không phải lúc nào cũng phải sửa lại phương thức nhận dữ liệu tại client của Hub. Điều này cũng đồng nghĩa với việc lúc nào module nào dùng thì có thể đăng ký nhận dữ liệu.
Tham khảo tuyển dụng javascript lương cao trên TopDev
Sau đây là code mẫu tôi viết cho chương trình chat đơn giản về sử dụng thư viện mở rộng trên
Trước tiên bạn cũng cài đặt SignalR và gắn thẻ script ở client
<
script
src
=
'/signalr/hubs'
></
script
>
<!-- file js mà hub sinh ra -->
<
script
src
=
'Hub.js'
></
script
>
<!-- Thư viện mở rộng của tôi -->
Code server để định nghĩa Hub
public class ExampleHub : Hub { public void ClientSendMessage(string userName, string msg, string color) { userName = userName.Trim(); if (userName.IsNull()) return; msg = msg.Trim(); if (msg.IsNull()) return; var data = new { userName, avatar = userName.First(), msg, time = DateTime.Now.ToString("HH:mm dd/MM/yyyy"), color }; Clients.AllExcept(Context.ConnectionId).receiveMessage(data, false); Clients.Client(Context.ConnectionId).receiveMessage(data, true); } }
Code javascript tại client để kết nối tới Hub
function ExampleHub() { $.extend(this, new Hub("", "exampleHub")); this.actionReceiveMessage = new Hub.ActionRegistry(); this.onBeforeStart = function () { var $this = this; // Client this.hub.client.receiveMessage = function (data, right) { $this.actionReceiveMessage.do(function (func) { func(data, right); }); }; // Server this.startDone = function () { }; this.clientSendMessage = function (userName, message, color) { this.onOk(function () { $this.hub.server.clientSendMessage(userName, message, color); }); } }; }
Ở đây các bạn có thể thấy ExampleHub
kế thừa tới Hub và gán 2 giá trị: hubUrl
= “” (Do server của hub nằm ngay tại server web của tôi) và hubName
= “exampleHub”.
Ở phía xử lý client có this.actionReceiveMessage
là đối tượng đăng ký nhận hành động muốn xử lý data gửi về từ server. Client muốn giao tiếp gửi request tới server thì thông qua this.onOk
để luôn đảm bảo chỉ thực hiện request khi ở trạng thái kết nối ổn định.
Và cuối cùng là giao diện hiển thị tôi định nghĩa một BoxChat như sau
function BoxChat() { this.ws = null; // là một instance của ExampleHub this.area = null; var template = null; var colors = { 0: "bg-danger text-white", 1: "bg-success text-white", 2: "bg-primary text-white", 3: "bg-warning text-white", 4: "bg-secondary text-white", 5: "bg-dark text-white", 6: "bg-orangered text-white" }; var names = { 0: "Sơn20", 1: "Dũng", 2: "Việt Anh", 3: "TuhiKing", 4: "Tàn Long", 5: "ButaKing", 6: "Osoft" }; var color = null; this.start = function () { color = colors[Core.random(6)]; var $this = this; template = this.area.find("[data-form=template] .direct-chat-msg"); var userNameInput = this.area.find("[name=userName]"); var messageInput = this.area.find("[name=message]").focus(); var butonSend = this.area.find("[data-form=button]"); userNameInput.val(names[Core.random(6)] + "." + Core.random(20)); // Tạo một tên ngẫu nhiên butonSend.click(function () { var userName = userNameInput.val(); if (userName == "") { Core.alert("Vui lòng nhập tên tài khoản để tán gẫu"); return; }; var message = messageInput.val(); if (message == "") { Core.alert("Vui lòng nhập nội dung để tán gẫu"); return; }; $this.ws.clientSendMessage(userName, message, color); }); messageInput.keypress(function (event) { if (event.keyCode == "13") { butonSend.click(); return false; } }); var formChat = this.area.find("[data-form=chat]"); this.ws.actionReceiveMessage.registry(function (data, right) { var chatItem = template.clone(); chatItem.find("[data-chat]").each(function () { $(this).html(data[$(this).attr("data-chat")]); }); chatItem.find("[data-chat=avatar]").addClass(data.color); if (right) chatItem.addClass("right"); formChat.append(chatItem); formChat.scrollTop(formChat[0].scrollHeight); messageInput.val("").focus(); }); } }
Tại hàm start
của BoxChat
tôi đăng ký hành động khi có message gửi về thì hiển thị nội dung tin nhắn lên. Như đã nói ở trên, actionRegistry
giúp đăng ký hành động nhận push từ server ở mọi module mà mình muốn mà không cần phải sửa lại hàm ở client trong hub.
Cuối cùng là khai báo và sử dụng
var ws = new ExampleHub(); ws.timeout = 2000; // Mặc định ws.start(); var boxChat = new BoxChat(); boxChat.ws = ws; boxChat.area = $("article"); boxChat.start(); // Ví dụ viết code đăng ký thêm một hành động nhận dữ liệu từ server push về // Thì hiển thị một notify bên góc phải trên cùng màn hình // Để cho thấy là có thể đăng ký sự kiện nhận dữ liệu ở mọi nơi. ws.actionReceiveMessage.registry(function (data, right) { new PNotify({ target: $("article"), text: data.userName + ":" + data.msg, type: "success", delay: 1000 }); });
Tại bài viết này tôi vẫn đang sử dụng asp.net SignalR mà chưa chuyển sang asp.net Core SignalR. Do chưa đủ điều kiện về vật chất, hạ tầng và nhất là hệ thống phần mềm hiện tại của tôi vẫn đang viết trên asp.net. Tuy nhiên với cách làm này của tôi thì chuyển sang asp.net Core tôi cũng sẽ làm tương tự. Và đây là chia sẻ nhỏ mà tôi đã làm trong thực tế.
Gửi cảnh báo khi nhân viên thêm phiếu chi với một mục đích chi nào đó bị quá giới hạn cho phép mà quản lý đã cấu hình
Click vào cảnh báo ở góc phải bên dưới màn hình xem ngay được nội dung cảnh báo
Tại nội dung cảnh báo. Click xem chi tiết phiếu để xem nhân viên đã thêm chi cho những mục đích gì
Chúc các bạn lập trình ngày càng tốt hơn. Nếu có thắc mắc các bạn hãy để lại bình luận nhé. Xin cảm ơn
Sơn 20
Bài viết gốc được đăng tải tại sonpc20.com
Có thể bạn quan tâm:
- 12 Thư viện JavaScript trực quan hoá dữ liệu hot nhất năm 2019
- 5 cách chia một mảng lớn thành nhiều mảng nhỏ trong Javascript
- 6 giải pháp tuyển dụng IT giúp thiết lập chiến lược chinh phục ứng viên tài năng
Tham khảo tìm việc IT hấp dẫn trên TopDev