多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Sails 的 SailsSocket 类详解:sails.io.js 多 Socket 连接与生命周期管理

Sails 的 SailsSocket 类详解:sails.io.js 多 Socket 连接与生命周期管理 Sails 的 SailsSocket 类详解sails.io.js 多 Socket 连接与生命周期管理【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails导读SailsSocket是 Sails 实时 MVC 框架中 socket 客户端sails.io.js的核心类它把底层的 Socket.IO 客户端包装成提供.get()、.post()、.request()等高层 API 的实例让前端可以用熟悉的 Ajax 风格与 Sails 后端通信。本文以仓库中的 SailsSocket.md 为主线完整讲解如何创建多个 SailsSocket 实例、管理其连接生命周期并结合同目录下的 methods.md 与 properties.md 及源码佐证深入每一个属性和高级方法。读完本文你将掌握默认io.socket的自动连接机制、用io.sails.connect()手动创建额外 Socket、连接状态检测、断开/重连策略以及如何在自动化测试等高级场景中利用多 Socket 连接。什么是 SailsSocketsails.io.js 的高层封装SailsSocket是sails.io.js库中的核心类。它的作用是包装低层 Socket.IO 客户端为每个 socket 实例提供更高级的方法如.get()、.post()使你能够以类似 Ajax 的方式与 Sails 应用通信。在浏览器中io.socket.post(/user)会被路由到 Sails 应用内部其处理方式与向同一路由发送 HTTP POST 请求完全一致——这正是sails.io.js最核心的设计理念见 sails.io.js.md 的 How does this work? 一节。默认的单例io.socket默认情况下sails.io.js在加载后几乎立即自动连接一个socketio.socket使客户端代码可以向特定的 Sails 服务器发送 socket 请求并接收服务器推送的事件和数据。对于 99% 的应用来说这就足够了。为什么需要 SailsSocket 类然而在某些高级使用场景包括自动化测试中从同一个 socket 客户端实例例如同一个浏览器标签页连接额外的 socket 会非常有用。为此Sails 暴露了SailsSocket类。你可以通过它创建多个相互独立的连接分别连接不同服务器或携带不同配置。底层原理虚拟请求解释器sails.io.js之所以能做到 socket 请求与 HTTP 请求同路由是因为它在底层发送的是带保留名称的 Socket.IO 消息Sails 后端会将这些消息交给虚拟请求解释器按照应用的路由与 blueprint 配置分发到对应的 policies/controllers 等。也就是说SailsSocket是对原生 Socket.IO 客户端的一种 无侵入 包装它暴露更高层的 API让 WebSocket 请求与普通 HTTP 请求复用同一套后端代码从而降低 WebSocket 入门门槛详见 sails.io.js.md 的 FAQ。创建 SailsSocket 实例自动创建页面加载时的 eager socket任何加载了sails.io.js的网页都会在页面加载时创建一个新的 SailsSocket 实例除非io.sails.autoConnect被设置为false。这个实例随后作为全局变量io.socket可用见 io.socket.md。关键时序细节sails.io.js库会等待事件循环的一个 tick约一个 event loop cycle然后才检查autoConnect是否启用并尝试连接。这个 等待一个 tick 的设计给了你在连接真正建立之前修改配置例如设置io.sails.url的机会。因此在浏览器中配置io.sails属性的代码必须紧跟引入sails.io.js的script标签之后script src/js/dependencies/sails.io.js/script script typetext/javascript io.sails.url https://myapp.com; /script !-- ...other scripts... --上面的示例会让 eager自动连接socket 改为尝试跨域连接运行在https://myapp.com的 Sails 服务器而不是默认的脚本所在服务器配置说明与示例均出自 sails.io.js.md。手动创建io.sails.connect()额外的 SailsSocket 实例可以通过调用io.sails.connect创建var newSailsSocket io.sails.connect();io.sails.connect([url], [options])的两个参数都是可选的io.sails上的属性如url、transports等会被用作默认值。当io.sails.autoConnect为false或你需要创建不止一个 socket 连接时就应当通过connect()手动创建详见 io.sails.md 的.connect()方法一节。提示关于 Grunt 资产管线如果你使用默认的 Grunt 资产管线会自动注入 script 标签官方文档建议将sails.io.js从pipeline.js中排除改为显式添加script标签。这样可以确保你的程序化配置如设置io.sails.url在 eager socket 开始连接之前被执行依据 sails.io.js.md。SailsSocket 属性详解SailsSocket 的属性在初始调用io.sails.connect时被设置socket 连接期间这些属性不可更改headers除外。一旦 socket 断开连接无论被动断开还是主动调用.disconnect()其属性就可以被修改直到 socket 再次连接。这意味着一个从某服务器断开连接的实例可以重新连接到另一台服务器而不会丢失其事件绑定或排队的请求见 properties.md。常用属性属性类型默认值说明urlstringio.sails.url的值socket 已连接或将要连接的 URL。transportsarrayio.sails.transports的值socket 尝试连接时所用的 transports。按顺序尝试且允许升级例如同时列出polling和websocket时会先建立 long-polling 连接再由服务器尝试升级为 websocket 连接。该设置应匹配 Sails 应用中的sails.config.sockets.transports。headersdictionaryio.sails.headers的值连接后该 socket 每次请求默认携带的头部字典。可通过.request()中的headers选项覆盖。高级属性属性类型默认值说明querystringio.sails.query的值与服务器初始连接使用的查询字符串。服务器端可在 controller action 中通过req.socket.handshake.query访问或在 socket 生命周期回调中通过handshake._query访问。注意sails.io.jsSDK 版本信息会被附加到你指定的查询字符串上。query的一个常见用途是设置nosessiontrue表示 Sails 应用不应将连接的 socket 与浏览器会话关联。initialConnectionHeadersdictionaryio.sails.initialConnectionHeaders的值仅 Node.js 环境可用浏览器中不可用。与初始连接一起发送的头部字典区别于上面的headers——那是在初始连接之后每次 socket 请求都会发送的头部。服务器端可在 controller action 中通过req.socket.handshake.headers访问或在 socket 生命周期回调中通过socket.handshake.headers访问。典型用途如发送cookie头完成初始握手使 socket 连接到先前建立的 Sails 会话。useCORSRouteToGetCookieboolean 或 stringio.sails.useCORSRouteToGetCookie的值仅与浏览器环境相关且仅当依赖默认的 Sails session session cookie 进行认证时才有意义。对于跨域 socket 连接可用该属性选择一个路由发送初始 JSONP 请求以获取 cookie从而建立正确的会话。该路由应返回字符串_sailsIoJSConnect();以允许连接继续。若为true使用 Sails 服务器上的默认/__getcookie路由若为false则在连接 socket 前不尝试联系远程服务器。注意该策略在部分默认阻止第三方 cookie 的浏览器包括某些 Safari 版本上可能失败。io.sails.*默认值io.sails对象可以为新的客户端 socket 提供默认值。例如设置io.sails.url http://myapp.com:1234会让每个新客户端 socket 默认连接到http://myapp.com:1234除非在io.sails.connect()调用中提供了url值。以下为io.sails中属性的默认值表格出自 properties.md属性默认值url浏览器中加载了sails.io.js脚本的页面 URLNode.js 中无默认值transports[websocket]headers{}queryinitialConnectionHeaders{}useCORSRouteToGetCookietrue注意url的默认值在浏览器与 Node.js 中不同这是由运行环境决定的——浏览器可以读取当前页面 URLNode.js 脚本则没有这种上下文。SailsSocket 方法详解SailsSocket 的大多数方法都可以在 socket 连接到服务器之前调用。对于请求类方法如.get()和.request()调用会被排队直到 socket 连接届时按顺序执行见 methods.md。这正是io.socket在页面加载后可以立即使用的根本原因。基础方法最常用的方法在 Socket Client 主参考章节中介绍包括.get()、.put()、.post()、.delete()、.request()、.on()和.off()。其中.request()是较底层的方法提供对请求 method、url、data、headers 的完全控制适合需要自定义请求的场景io.socket.request({ method: get, url: /user/3/friends, data: { limit: 15 }, headers: { x-csrf-token: ji4brixbiub3 } }, function (resData, jwres) { if (jwres.error) { console.log(jwres.statusCode); // e.g. 403 return; } console.log(jwres.statusCode); // e.g. 200 });回调的jwres是一个 JSON WebSocket Response 对象包含headers、body和statusCode其中resData jwres.body详见 socket.request.md。高级方法连接生命周期管理除基础通信与事件监听方法外每个 SailsSocket 实例包括io.socket都暴露了几个处理服务器连接的方法.isConnected()判断 SailsSocket 实例当前是否已连接到服务器已建立连接时返回true。io.socket.isConnected();.isConnecting()判断 SailsSocket 实例当前是否正在连接服务器的过程中正在尝试连接时返回true。io.socket.isConnecting();.mightBeAboutToAutoConnect()检测 SailsSocket 实例是否已加载但尚未完全配置或尚未尝试自动连接。sails.io.js库会等待事件循环的一个 tick然后才检查autoConnect是否启用并尝试连接。这个等待周期允许你在建立连接之前配置 SailsSocket 实例例如设置io.sails.url。mightBeAboutToAutoConnect()在sails.io.js已加载、但所需的 tick 尚未过去时返回true。io.socket.mightBeAboutToAutoConnect();.disconnect()将 SailsSocket 实例与服务器断开如果 socket 已经断开则抛出错误。io.socket.disconnect();.reconnect()在 socket 被断开无论被动断开还是通过调用.disconnect()之后将其重新连接到服务器。实例使用其当前配置的 属性 进行连接。如果 socket 已连接到服务器.reconnect()会抛出错误。io.socket.reconnect();当实例处于断开状态时其属性可以被修改。这意味着一个从某服务器断开的实例可以重新连接到另一台服务器而不会丢失其事件绑定或排队的请求。.removeAllListeners()停止监听 SailsSocket 实例上的所有服务器相关事件包括connect和disconnect。io.socket.removeAllListeners();实战多 Socket 连接的典型场景场景一自动化测试自动化测试是多 Socket 连接最常见的用途之一。默认的io.socket只连接一个服务器但测试中常常需要用一个 socket 模拟用户 A例如已认证、订阅了某房间用另一个 socket 模拟用户 B例如未认证验证 A 能收到广播而 B 不能收到。实现方式// 关闭默认 eager socket io.sails.autoConnect false; // 手动创建两个独立的 SailsSocket 实例 var adminSocket io.sails.connect(http://localhost:1337, { headers: { cookie: sails.sid... } // 模拟已登录会话 }); var guestSocket io.sails.connect(http://localhost:1337);由于sails.io.js会等待一个事件循环 tick 后才自动连接你可以在浏览器脚本中放心地先修改io.sails.autoConnect false再调用connect()。场景二多服务器或会话隔离同一个页面中不同 socket 可以携带不同的query如nosessiontrue表示不与浏览器会话关联、不同的headers或连接不同的服务器url。例如var socketWithSession io.sails.connect(http://myapp.com); var socketNoSession io.sails.connect(http://myapp.com, { query: nosessiontrue });场景三连接状态驱动的 UI利用.isConnected()、.isConnecting()和mightBeAboutToAutoConnect()可以构建更精确的连接状态指示。配合.on()监听connect/disconnect事件可以在连接中断时显示错误提示或手动调用.reconnect()恢复io.socket.on(disconnect, function onDisconnect() { console.log(This socket lost connection to the Sails server); // 例如显示 请检查网络连接 的提示 }); io.socket.on(connect, function onConnect() { console.log(This socket is now connected to the Sails server.); });注意截至 Sails v1socket 客户端默认禁用自动重连io.sails.reconnection默认false。由于断开期间 UI 可能错过 socket 通知官方文档建议自行处理相关逻辑例如提示 检查网络连接。若确实需要自动重连可设置io.sails.reconnection true依据 io.sails.md 与 io.socket.on.md。场景四断线换服务器重连利用 断开状态下可修改属性 的机制可以实现从服务器 A 切换到服务器 B 而不丢失事件绑定与排队请求// 假设 socketA 已连接 socketA.disconnect(); socketA.url http://backup-server.com; socketA.reconnect(); // 使用新 URL 重新连接事件绑定仍在注意事项与最佳实践排队机制SailsSocket 的大多数方法可在连接前调用请求与事件绑定会被排队连接建立后按序回放。因此不必等待connect事件即可使用io.socket依据 io.socket.on.md 的 The connect event 一节。transports需与服务器一致客户端transports应匹配 Sails 应用中的sails.config.sockets.transports否则可能出现连接失败。useCORSRouteToGetCookie的浏览器限制在默认阻止第三方 cookie 的浏览器含部分 Safari 版本上该策略可能失败。off()并不阻止消息接收.off()只是阻止指定事件处理函数触发并不会阻止服务器向该 socket 发送消息。若要彻底停止接收广播例如管理员被禁言后应在服务器端使用sails.sockets.leave()或.unsubscribe()/.unwatch()取消订阅。事件命名约定监听资源化 PubSub 与 blueprint 的 socket 消息时事件名始终等于对应 model 的 identity小写。例如名为 UserComment 的 model其 identity因而也是UserComment.publish()使用的 socket 事件名是usercomment。会话关联默认情况下socket 连接会通过初始握手中的cookie头与当前浏览器会话关联若不想关联在 socket 连接前设置io.sails.query nosessiontrue见 sails.io.js.md 的 FAQ。参考资源SailsSocket 类文档SailsSocket 方法参考SailsSocket 属性参考Socket clientsails.io.js总览io.sails全局配置对象io.socket默认实例io.socket.request()io.socket.on() / off()sails.sockets 服务器端 API【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表