如何用Socket.io和Node.js开发一个大型的聊天应用程序

在过去的几个月中,我一直在使用Socket.io,开发一个相当复杂的聊天室,踢/禁止/版主/朋友等应用程序。

在开发过程中,我重写了这个应用程序好几次,而且还在为我的代码而战。

我非常喜欢JavaScript,但是我发现在应用程序不断增长的时候很难保持它。 我已经阅读了大量有关如何编写聊天应用程序的“教程”,但都涵盖了最基本的方面。 GitHub上的所有示例应用程序也是如此,甚至是我在网上find的大多数聊天应用程序(其中大多数只是简单的即时消息,没有任何用户pipe理)。

有些用例对我来说太荒谬了,比如踢一个房间的用户。

  • 主持人点击一个踢button – >发送事件到服务器
  • 服务器将用户名与套接字配对(或者只是广播给所有用户,并在客户端进行过滤) – >发送给他踢的事件
  • 用户向服务器发出注销事件,并且还显示他被踢的消息(注销只是我执行的处罚)
  • 用户将从聊天室的用户列表中删除 – >将当前用户列表发送给房间中的所有用户

这似乎不太复杂,但是当我添加所有在客户端发生的callback来pipe理UI(因为我使用AngularJS,我使用事件在控制器之间进行通信)以及服务器端的大量callback,因为一切都是非阻塞的,我觉得这个testing真的很难。

在客户端还有另外一个问题,我必须在多个地方监听套接字事件,所以我必须有一种单例全局套接字对象,并在多个地方挂接事件监听器。

我做错了什么,或者是这个callback地狱的工作与websockets没有办法的结果吗?

有没有什么方法可以使开发这样的应用程序更容易? 例如替代技术到Socket.io? 到目前为止,我只find了5个月前上次提交的NowJS和meteor ,这真的很酷,但是看看网站看起来并不稳定。

只要用我的朋友的承诺。 jQuery有他们内置的,但在nodejs方面,你可以使用q库。 不要写没有他们的asynchronous代码! 他们稍微习惯一下,但是一旦你在写思维的时候写asynchronous代码就轻而易举了。

还有像asynchronous这样的库,它提供了围绕callback代码的实用函数。 但是不要让人气骗你。 承诺是甜蜜的。

对于asynchronous代码testing,您不需要比nodeunit进步得多 ,它可以为您提供一个简单的done()函数,您可以在testing完成后调用它,因此只要您喜欢就可以运行。

哇,让我们把它分解成实际的问题,因为我没有看到很多的定义:

从一个房间踢用户:

  • 主持人点击删除button(发出应该包含roomID和用户ID)
  • 服务器代码从Room对象中删除用户,并将消息发送给房间中已被踢出用户ID的每个用户。 如果之前有用户套接字连接(roomID),那么服务器代码如下所示:

     sio.sockets.to(roomID).emit('kicked', { userID: uid }); 

就这样。 在客户端代码中,你应该收到这个“踢”事件,并有这样的代码:

 if (data.removedUserID == myUserID) alert('You have been kicked by moderator'); else removeUserFromList(userID); 

您不应该让客户发出他要离开的消息,因为恶意用户可能会写一个忽略禁止的客户端。

我必须在多个地方监听套接字事件

为什么? “多个地方”是什么意思?

有没有什么方法可以使开发这样的应用程序更容易?

  • 不要只是潜入代码。 想想人们如何直接沟通。 客户端是发送消息的人,服务器是邮局。 稍后翻译代码中的逻辑。
  • 确保服务器是唯一的控制器,客户端只给出命令并显示状态,而不做任何逻辑。

我开发了一个4000位的多人游戏,聊天只是其中的一小部分。 我每天有大约60,000个用户在玩它。 一切都是纯粹的socket.io代码与一些Express / EJS来获得屏幕,我无法想象它变得更简单。 特别是不要使用一些“魔法”库来隐藏所有来自我的通信,并确实引入它自己的一组等待被发现和修复的错误。

披露:我是独家开发者。

我有或多或less的相同的问题,它归结为通常的callback金字塔,可以解决许多图书馆(有几十个, 只是看看 。

在我发现一个主要的缺点之前,我非常高兴:你不能嵌套它们(一个调用更多步骤的步骤)。 这对我来说非常重要,我不太喜欢所有其他的asynchronous库,因为它们提供了太多我不会用到的function,所以我写了一个独家新闻 。

这是一个简单的lib,它试图帮助所有其他的asynchronous库,模仿一些个人风格的步骤。 看看例子,它可能适合您的需求。

你也可以看看derby.js 。 它是一个非常类似于meteor的框架,但是构build在npm,socket.io,express等所有node.js“好东西”上。Derby包含一个强大的数据同步引擎Racer,它自动同步浏览器,服务器和数据库。 他们甚至有一个基本的聊天的例子 。

meteor使用了很多自己的技术(光纤,自己的包pipe理器)。 就像meteor德比依然处于阿尔法阶段,但在上一次获得了很多吸引力。 Airbnb最近宣布,他们将考虑未来的德比实施。

一些更多的信息:

你的问题很难回答,但我可以向你保证,我感觉到你的痛苦…即使没有node.js,callback也可能很快就会变得毛茸茸,asynchronoustesting真的很难做到。 我想我应该说:努力做好,但这听起来像我知道如何轻松做到这一点,我不这样做。 背景问题是asynchronous开发很难,就像以前的并发编程一样。

我不认为一个不同的websocket库会帮助你,甚至完全避免websocket。 有什么可以帮助你的是使用一些技巧。 上面的安迪雷暗示着诺言; 我没有广泛使用它们,但是值得一试。

自我诊断是你的朋友。 JavaScript是一个dynamic的语言,没有一个types系统值得它的盐,并掩盖空对象; 只有大量的自动testing可以确保质量。 但正如你所说的testing可能真的很难。

另一个窍门是:用疯狂的方式来testing你的应用 发送仪器事件并在您的testing中检查它们。 我们在一个无头浏览器(PhantomJS)的基础上构build了一个很酷的testing套件,我们用JavaScript来检查客户端是否发送了正确的事件; 它可能很难debugging,但它的工作原理。

当然,通常的devise秘诀有助于:KISS,YAGNI等等,但是我不会侮辱你的智力。 祝你好运。