命名空间

命名空间是一种通信通道,允许您通过单个共享连接(也称为“多路复用”)拆分应用程序的逻辑。

Namespace diagram

介绍

每个命名空间都有自己的:

  1. io.of("/orders").on("connection", (socket) => {
  2. socket.on("order:list", () => {});
  3. socket.on("order:create", () => {});
  4. });
  5. io.of("/users").on("connection", (socket) => {
  6. socket.on("user:list", () => {});
  7. });
  1. const orderNamespace = io.of("/orders");
  2. orderNamespace.on("connection", (socket) => {
  3. socket.join("room1");
  4. orderNamespace.to("room1").emit("hello");
  5. });
  6. const userNamespace = io.of("/users");
  7. userNamespace.on("connection", (socket) => {
  8. socket.join("room1"); // distinct from the room in the "orders" namespace
  9. userNamespace.to("room1").emit("holà");
  10. });
  1. const orderNamespace = io.of("/orders");
  2. orderNamespace.use((socket, next) => {
  3. // ensure the socket has access to the "orders" namespace, and then
  4. next();
  5. });
  6. const userNamespace = io.of("/users");
  7. userNamespace.use((socket, next) => {
  8. // ensure the socket has access to the "users" namespace, and then
  9. next();
  10. });

可能的用例:

  • 您想创建一个只有授权用户才能访问的特殊命名空间,因此与这些用户相关的逻辑与应用程序的其余部分分离
  1. const adminNamespace = io.of("/admin");
  2. adminNamespace.use((socket, next) => {
  3. // ensure the user has sufficient rights
  4. next();
  5. });
  6. adminNamespace.on("connection", socket => {
  7. socket.on("delete user", () => {
  8. // ...
  9. });
  10. });
  • 您的应用程序有多个租户,因此您希望为每个租户动态创建一个命名空间
  1. const workspaces = io.of(/^\/\w+$/);
  2. workspaces.on("connection", socket => {
  3. const workspace = socket.nsp;
  4. workspace.emit("hello");
  5. });

主命名空间

到目前为止,您与称为/的主名称空间进行了互动。 io实例继承了它的所有方法:

  1. io.on("connection", (socket) => {});
  2. io.use((socket, next) => { next() });
  3. io.emit("hello");
  4. // are actually equivalent to
  5. io.of("/").on("connection", (socket) => {});
  6. io.of("/").use((socket, next) => { next() });
  7. io.of("/").emit("hello");

有些教程可能还会提到io.sockets,它只是io.of("/").

  1. io.sockets === io.of("/")

自定义命名空间

要设置自定义命名空间,您可以of在服务器端调用该函数:

  1. const nsp = io.of("/my-namespace");
  2. nsp.on("connection", socket => {
  3. console.log("someone connected");
  4. });
  5. nsp.emit("hi", "everyone!");

客户端初始化

同源版本:

  1. const socket = io(); // or io("/"), the main namespace
  2. const orderSocket = io("/orders"); // the "orders" namespace
  3. const userSocket = io("/users"); // the "users" namespace

跨域/Node.js 版本:

  1. const socket = io("https://example.com"); // or io("https://example.com/"), the main namespace
  2. const orderSocket = io("https://example.com/orders"); // the "orders" namespace
  3. const userSocket = io("https://example.com/users"); // the "users" namespace

在上面的示例中,只会建立一个 WebSocket 连接,并且数据包会自动路由到正确的命名空间。

请注意,在以下情况下将禁用多路复用:

  • 同一命名空间的多次创建
  1. const socket1 = io();
  2. const socket2 = io(); // no multiplexing, two distinct WebSocket connections
  • 不同的域
  1. const socket1 = io("https://first.example.com");
  2. const socket2 = io("https://second.example.com"); // no multiplexing, two distinct WebSocket connections
  1. const socket1 = io();
  2. const socket2 = io("/admin", { forceNew: true }); // no multiplexing, two distinct WebSocket connections

动态命名空间

也可以使用正则表达式动态创建命名空间:

  1. io.of(/^\/dynamic-\d+$/);

或具有功能:

  1. io.of((name, auth, next) => {
  2. next(null, true); // or false, when the creation is denied
  3. });

您可以在事件中访问新的命名空间connection

  1. io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
  2. const namespace = socket.nsp;
  3. });

方法的返回值of()就是我们所说的父命名空间,你可以从中:

  1. const parentNamespace = io.of(/^\/dynamic-\d+$/);
  2. parentNamespace.use((socket, next) => { next() });

中间件将自动在每个子命名空间上注册。

  1. const parentNamespace = io.of(/^\/dynamic-\d+$/);
  2. parentNamespace.emit("hello"); // will be sent to users in /dynamic-1, /dynamic-2, ...

命名空间 - 图2警告

现有命名空间优先于动态命名空间。例如:

  1. // register "dynamic-101" namespace
  2. io.of("/dynamic-101");
  3. io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
  4. // will not be called for a connection on the "dynamic-101" namespace
  5. });

完整API

可以在此处找到命名空间实例公开的完整 API 。