如何通过 SignalR 实现“谁在打字”功能?

Posted

技术标签:

【中文标题】如何通过 SignalR 实现“谁在打字”功能?【英文标题】:How to implement 'Who is typing' feature via SignalR? 【发布时间】:2014-11-03 17:14:29 【问题描述】:

基本上,我正在我的网站中实现 SignalR 聊天。我已经可以向所有连接的用户发送消息,现在我希望添加“谁在打字”功能。我正在尝试将它添加到 $('#message').keypress 函数中,它可以工作,但现在我无法向用户发送消息。

我做错了什么?

去掉$('#message').keypress后可以发送消息

没有删除 $('#message').keypress 无法发送消息

我的html

<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" class="btn btn-default" />
<input type="hidden" id="displayname" />
<label id="isTyping" />
<ul id="discussion"></ul>

下面是脚本:

<!--SignalR script to update the chat page and send messages.-->
<script type="text/javascript">
    $(function () 
        // Reference the auto-generated proxy for the hub.
        var chat = $.connection.chatHub;
        // Create a function that the hub can call back to display messages.

        chat.client.broadcastMessage = function (name, message) 
            $('#discussion').append('<li><strong>' + name
                + '</strong>:&nbsp;&nbsp;' + message + '</li>');
        ;

        chat.client.sayWhoIsTyping = function (name) 
            $('#isTyping').html('<em>' + name + ' is typing...</em>');
            setTimeout(function () 
                $('#isTyping').html('&nbsp;');
            , 5000);
        ;

        // Get the user name and store it to prepend to messages.
        $('#displayname').val(prompt('Enter your name:', ''));
        // Set initial focus to message input box.
        $('#message').focus();

        // Start the connection.
        $.connection.hub.start().done(function () 

            $('#sendmessage').click(function () 
                var encodedName = $('<div />').text($('#displayname').val()).html();
                var encodedMsg = $('<div />').text($('#message').val()).html();
                chat.server.sendPublic(encodedName, encodedMsg);
                $('#message').val('').focus();
            );

            $('#message').keypress(function (e) 
                if (e.which == 13) 
                    var encodedName = $('<div />').text($('#displayname').val()).html();
                    var encodedMsg = $('<div />').text($('#message').val()).html();
                    chat.server.sendPublic(encodedName, encodedMsg);
                    $('#message').val('').focus();
                 else 
                    var encodedName = $('<div />').text($('#displayname').val()).html();
                    chat.server.isTyping(encodedName);
                
            );
        );



    // This optional function html-encodes messages for display in the page.
    function htmlEncode(value) 
        var encodedValue = $('<div />').text(value).html();
        return encodedValue;
    

以下是我的 Hub 代码:

    public void SendPublic(string name, string message)
    
        // Call the addNewMessageToPage method to update clients
        Clients.All.broadcastMessage(name, message);
    

    public void IsTyping(string name)
    
        SayWhoIsTyping(name);
    

    public void SayWhoIsTyping(string name)
    
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
        context.Clients.All.sayWhoIsTyping(name);
    

【问题讨论】:

【参考方案1】:

在您的服务器上,您的ChatHub 中必须有两个方法,名称为:

public void IsTyping (string html) 

    // do stuff with the html
    SayWhoIsTyping(html); //call the function to send the html to the other clients


public void SayWhoIsTyping (string html)

    IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
    context.Clients.All.sayWhoIsTyping (html);

这个过程是如何工作的?

您捕捉到您的一位客户正在键入的事件,即使用 javascript 中的按键功能。然后,您使用所需的 html 从服务器调用一个函数,其中包含名称和其他信息。服务器接收信息,处理它,然后从客户端调用一个函数来显示谁在打字。

在您的情况下,来自服务器的 IsTyping 方法将处理来自客户端的信息,来自服务器的 SayWhoIsTyping 方法将调用客户端来处理所需的信息。

编辑您的评论:

我建议像这样从 javascript 修改函数:

chat.client.sayWhoIsTyping = function (name) 
    $('#isTyping').html('<em>' + name + ' is typing...</em>');
    setTimeout(function () 
        $('#isTyping').html('&nbsp;');
    , 5000);
;

$('#message').keypress(function(e) 
    if (e.which == 13) 
        $('#sendmessage').trigger('click');
     else 
        var encodedName = $('<div />').text($('#displayname').val()).html();
        chat.server.isTyping(encodedName);
    
);

并删除 $(document).keypress函数。

【讨论】:

感谢您的有用评论〜我可以将“谁在打字...”发送给所有连接的用户。但是,我无法将用户类型消息发送给用户。你知道发生了什么吗?我已经在上面编辑了我的代码~ 但是如果我删除 $('#message').keypress 函数,我可以将这些用户类型的消息发送给用户 一般情况下,使用SignalR时,服务端方法必须以大写字母开头,而从客户端调用时,它们应该以小写字母开头,即public void SendPublic(string name, string message) 此外,与'#message' 元素相关联的按键功能将取代文档中的按键功能,文档是向服务器发送消息的功能,因此无论何时按下一个键,也就是说,只有与您的'#message' 相关联的按键功能会被调用。看看我编辑的答案,它提供了这两者的组合。 我终于找到了我的问题....因为我使用 而不是 【参考方案2】:

在集线器类服务器端

public void UserTyping(groupName)

    var userName = "Get current user's name";
    //client method here
    Clients.OthersInGroup(groupName).OtherUserIsTyping(userName);

客户端

<textbox id="message"></textbox>
<span id="userTyping"></span>

var keyPressCount = 0;

$("#message").on("keypress", function () 
    if (e.which == 13) 
       $('#sendmessage').trigger('click');
     
    else 
       // Don't want to call the server on every keypress
       if (keyPressCount++ % 10 == 0) 
        chatHub.server.userTyping("myChatGroup");
       
    
);

chatHub.client.OtherUserIsTyping = function (userName) 
    $("#userTyping").html(userName + " is typing...");
;

【讨论】:

以上是关于如何通过 SignalR 实现“谁在打字”功能?的主要内容,如果未能解决你的问题,请参考以下文章

SignalR——聊天室的实现

[Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能

如何使用signalr实现离线聊天

基于SignalR实现B/S系统对windows服务运行状态的监测

在 Asp.NET MVC 中使用 SignalR 实现推送功能

ASP.NET SignalR 应用并实现群聊功能 (开源代码)