如何在聊天中向所有人发出实时“用户正在打字”的通知

时间:2012-05-13 01:08:59

标签: php javascript jquery ajax node.js

我想用jQuery和PHP编写聊天应用程序。我需要帮助的部分是实时用户“Evx”正在键入消息,然后实时向所有其他用户显示该消息。这类似于Skype有笔的方式../以及Facebook如何在用户输入时发出通知。

我需要的是有关如何轻松完成“用户正在打字”的实时逻辑步骤和信息的一些帮助,但仍然可以像其他任何方式一样工作。

这是我到目前为止所尝试的内容:

//time delay before ajax call
var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
    };
})();

$('#usermsg').keydown(function() {
    if ($('#usermsg').val().length === 5) {
        delay(function() {
            $.ajax({
                url: "addusertyping.php",
                cache: false,
                success: function() {

                }
            });
        }, 5000);
    }
});

$('#usermsg').keyup(function() {
    if ($('#usermsg').val().length >= 6) {
        // here I should basically check for 
          // an update from server or what not.
    }
});​

有人可以解释一下如何实现用户实时打字的步骤和信息,使用我上面尝试过的作为起点吗?

1 个答案:

答案 0 :(得分:11)

Facebook和Google Talk等网站在实施聊天时使用的方法是使用Comet或Reverse AJAX来利用Web的请求/响应模型的解决方案。

Web 1.0:

在传统的Web 1.0实现中,例如您的浏览器,浏览器会向服务器发起请求。服务器使用客户端代码在视图中呈现的数据进行响应。

当我们只是将用户从一个页面移动到另一个页面或者我们正在响应用户发起的事件时,这非常有用。但是,在管理由服务器启动的事件时,这种方法本质上存在缺陷。

在您的示例中,为了模拟实时更新,您必须使用连续轮询请求来锤击服务器以检查更新。这相当于汽车后座的小孩经常不断地问他的父母"我们在那里吗?我们在那里吗?"一次又一次,没有失败。这不仅会占用大量带宽,而且当连接的客户端数量增加时,会在服务器上产生很大的负载。

Comet / Reverse AJAX:

由于服务器无法在没有请求的情况下启动对浏览器的响应,因此称为"反向AJAX"或者" Comet"用于模拟服务器将事件通知推送到客户端的过程。

Comet背后的一般前提是浏览器打开与服务器的连接,然后服务器保持该连接无限期打开。当服务器具有需要传递给所有连接的客户端的更新时,它然后将响应发送回客户端,完成请求/响应周期。收到响应后,客户端立即向服务器发送另一个请求,服务器再次保持打开状态,直到下次更新。

有适用于PHP的Comet解决方案,因此您可以使用现有平台完成此任务;但是,我不能推荐任何。您还需要一个客户端库来方便打开Comet连接。查看Dojo Cometd JavaScript Library

Comet是实现聊天解决方案的两个卓越解决方案之一,另一个是WebSockets。但是,在某些浏览器中仍然缺乏对WebSockets的支持。

在寻找有助于Comet的库时,选择一个有助于Continuations的库也是一个好主意,这有助于确保等待发送响应的线程可以被释放以执行其他任务而不是懒散地等着。有了这样的解决方案,一些Comet服务器可以轻松扩展到超过20,000个连接!

这是一篇描述How to Implement Comet on PHP的文章。此外,您可能会发现此StackOverflow问题与describes the challenges of using Comet on PHP一样有用。

设计注意事项:

我们在开发聊天解决方案时犯的第一个错误就是没有将消息视为更抽象的子类。相反,我们从服务器发送到前端的信息只是一个"聊天消息"。但是,随着产品的推进,我们很快发现可以使用相同的Comet连接向浏览器发送命令,而不仅仅是消息。

因此,要实现您的用户输入",您可能需要JavaScript中的处理程序,首先确定服务器的更新是否是新消息,或者是"显示用户XYX正在输入"命令。一个好的设计还可以确保您可以将Comet连接用于从服务器启动的其他类型的更新。

最后,您的用户输入消息应该有一些延迟,这样当用户输入时,他或她的浏览器只会每X秒通知服务器一次。如果您将用户键入绑定到一个按键事件,该事件只是简单地使用AJAX请求来破坏服务器,那么您只需将Comet连接降级为轮询。

在收件人端,您很可能希望实现超时功能,以便在键入的用户停止发送"用户键入"用户键入时,用户输入消息会自动消失。请求到服务器。或者,该用户的浏览器可以发送"用户不再输入"如果浏览器在他或她的文本框为空时发送请求,例如当用户对输入的文本进行退格时,则会显示消息。

简易解决方案?:

最后,我想补充一点,这将涉及学习曲线,因为您必须从服务器的角度考虑Web,而不是将数据推送到客户端。这将涉及到您的大量研究和奉献,以及尝试示例并深入了解您应如何处理应用程序的设计。这是迄今为止掌握这种技术的最好方法之一,但它也可能是令人生畏的。请务必花时间阅读示例,亲自尝试,如果遇到困难,您可以随时寻求帮助。