Sails 高级用法:深入掌控 `sails` 应用实例(全局变量、hooks 字典与多实例创建)
后端【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址https://gitcode.com/gh_mirrors/sa/sails点击查看免费下载本篇指南聚焦 Sails 框架中sails应用对象的高级用法如何按需禁用sails全局变量并从 action、helper 或请求对象中安全地引用应用实例如何通过sails.hooks字典访问已加载的核心钩子与第三方钩子如何通过sails.io直接操作底层 socket.io 服务器以及如何在单进程内创建多个相互独立的 Sails 应用实例new Sails()。读完本文你将掌握编写测试、开发自定义钩子、迁移旧 Socket.io 代码等进阶场景下的标准做法。什么是高级用法Sails 框架的大多数用户只需要sails应用对象上几个基础方法如sails.lift()、sails.config、sails.log等即可完成日常工作。但如果你遇到以下场景就需要深入了解sails对象上那些较少被使用的成员需要同时存在多个 Sails 应用实例例如为 Sails 核心编写测试、在同一进程内跑多套应用配置需要禁用全局变量例如避免污染全局命名空间或在无全局变量环境下运行需要访问已加载的钩子hooks调用第三方钩子暴露的方法需要绕过sails.sockets.*封装、直接与底层 socket.io 交互例如迁移遗留的 Socket.io 代码。此外如果你考虑向 Sails 贡献代码也需要了解这些内部机制并可以参考Sails 核心的加载顺序。禁用sails全局变量Sails 官方推荐在应用代码中使用sails全局变量。但在某些场景下你可能希望关闭它同一进程内需要存在多个 Sails 应用实例时全局sails会指向歧义项目规范不允许使用全局变量例如严格模块化的代码库、自动化测试、命令行脚本、定时任务等。Sails 提供了一种机制来禁用自动全局化——通过sails.config.globals配置控制详见 sails.config.globals。在仓库源码 lib/app/private/exposeGlobals.js 中可以确认这套逻辑的实现细节如果sails.config.globals未定义Sails默认假定为false不暴露任何全局变量以便程序化使用sails.lift()/sails.load()在测试、命令行脚本、定时任务中更直观sails.config.globals必须是false或一个字典纯 JavaScript 对象否则抛出E_BAD_GLOBAL_CONFIG错误当sails.config.globals.sails ! false时才会执行global[sails] sails见 lib/app/private/exposeGlobals.js且该值必须是布尔值true或false同理_Lodash、async、models等全局变量也受sails.config.globals对应子键控制。需要说明的是config/globals.js样板文件的默认设置与上述未指定时默认false并不冲突——在控制器 action 等应用代码中使用全局变量依然是官方推荐做法两者面向不同的使用场景。禁用全局变量后的替代引用方式如果sails全局变量被禁用你仍可以从应用内几乎任何地方拿到应用实例场景引用方式说明action 的fn中this.sailsSails 会自动将应用实例绑定到 action 函数的this上下文helper 的fn中this.sails与 action 相同helper 的this上也挂载了应用实例任意传入请求中req._sails每个请求对象上都挂载了创建它的应用实例引用req._sails在 Sails 核心代码中被大量使用例如蓝图blueprint相关 action 几乎全部通过req._sails.config、req._sails.models、req._sails.hooks访问配置、模型与钩子参见 lib/hooks/blueprints/actions/find.js、lib/hooks/blueprints/actions/create.js、lib/hooks/blueprints/actionUtil.js 等。这验证了请求对象持有应用实例引用是框架的通用约定。高级属性sails.hookssails.hooks是一个字典包含所有已加载的 Sails 钩子以各自的identity标识名为键索引。访问钩子实例你可以通过sails.hooks访问已安装钩子的属性和方法从而扩展 Sails// 调用 sails-hook-email 之类的第三方钩子暴露的方法 sails.hooks.email.send(...);也可以用它访问 Sails 的核心钩子做高级操作例如在 action 中判断 pubsub 钩子是否可用if (sails.hooks.pubsub) { // 执行实时消息相关操作 }identity 的命名规则默认情况下钩子的 identity 是其文件夹名的小写版本并去除任何sails-hook-前缀。例如从node_modules/sails-hook-email加载的钩子默认 identity 为email可通过sails.hooks.email访问从node_modules/scope/sails-hook-foo带 npm 命名空间加载的钩子identity 同样会去除命名空间和sails-hook-前缀。该逻辑在仓库源码中有精确实现。在 lib/hooks/moduleloader/index.js 的loadUserHooks中框架会依次按以下优先级确定安装型钩子的名称钩子package.json中sails.hookName字段显式声明的名称sails.config.installedHooks[identity].name配置指定的名称即通过installedHooks配置项改变 Sails 加载安装型钩子的方式否则使用模块名并去除 npm 命名空间与sails-hook-前缀identity.replace(/^(.?[\/\\])?(sails-hook-)?/, )。同时源码还展示了相关的边界行为api/hooks下的项目钩子优先级高于node_modules中的同名钩子node_modules中发现同名钩子会覆盖核心钩子并输出 verbose 日志且只有声明为 Sails 钩子package.json中sails.isHook为真并记录在应用package.json依赖中的模块才会被加载lib/hooks/moduleloader/index.js。关于钩子本身的更多信息包括如何编写钩子、initialize/configure/defaults等生命周期方法可参考钩子概念文档以及仓库中的钩子基类实现 lib/hooks/index.js。高级属性sails.iosails.sockets.*系列方法如 sails.sockets.broadcast、sails.sockets.join 等提供的 API 开箱即用足以覆盖绝大多数应用的实时通信需求且使用它们能让你的应用在未来底层实现变更时保持兼容。但如果你正把遗留的原生 Socket.io 应用代码迁移到 Sails直接与 Socket.io 对话会更方便。为此Sails 通过sails.io暴露了底层 socket.io 服务器实例io的原始访问权// 直接访问底层 socket.io 服务器实例 sails.io.sockets.emit(someEvent, { hello: world });Sails 将socket.io作为核心钩子 sails-hook-sockets 的依赖打包分发该钩子是一个安装型核心钩子随应用安装于node_modules中而非位于仓库的lib/hooks/目录下。需要特别强调的是请谨慎直接使用 Socket.io。官方推荐优先使用sails.sockets.*封装方法其方法与用途可参考 sails.sockets 参考文档因为sails.sockets.*对客户端连接方式浏览器标签页、iOS 应用、IoT 设备完全透明它面向未来能抵御底层 socket.io 实现变动带来的破坏对于更上层的资源型 PubSub需求Sails 内置蓝图 API 正是使用它可以进一步使用resourceful pubsub 方法。应用对象从哪里来Sails 应用实例会在你第一次require(sails)时自动创建。这正是生成的app.js中发生的事情var sails require(sails);之后任何对require(sails)的调用都会返回同一个应用实例——这就是 Sails 应用实例常被称为单例singleton的原因。该行为在仓库源码中有明确实现。在 lib/app/index.js 中module.exports SailsFactory; function SailsFactory() { return new Sails(); } // Backwards compatibility for Sails singleton usage: var singleton SailsFactory();也就是说模块加载时即执行了一次SailsFactory()产出的singleton被缓存在模块作用域内后续每次require(sails)命中的都是 Node.js 模块缓存的同一对象。而真正的构造器定义在 lib/app/Sails.jsSails继承自events.EventEmitter因此sails.on()/sails.emit()等事件机制可用构造时会初始化sails.logCaptainsLog 实例、sails._actions、sails._actionMiddleware构建路由器实例并混入load()方法以及一系列绑定好this上下文的方法lift、lower、request、initialize、exposeGlobals等。单例实例上还额外暴露了isLocalSailsValid、isSailsAppSync两个静态方法见 lib/app/index.js用于校验本地 Sails 安装与当前应用是否为合法 Sails 应用。创建新的应用对象高级当你在实现一些非常规功能时——例如为 Sails 核心编写测试——可能需要在一个进程内创建多个Sails 应用实例。此时不应该使用require(sails)返回的单例实例因为这可能引发预期之外的行为配置互相污染、事件监听重复等。正确做法是通过 Sails 构造函数获取实例var Sails require(sails).constructor; var sails0 new Sails(); var sails1 new Sails(); var sails2 new Sails();每个应用实例sails0、sails1、sails2都可以使用不同的配置分别加载load或启动lift互不干扰// 实例 1默认配置 sails0.load(function(err) { // ... }); // 实例 2带配置覆盖 sails1.lift({ port: 1338, environment: test }, function(err, app) { // ... });从源码看lib/app/load.js 还特别处理了已 lower 的应用实例不可再次 load/lift的情况其错误提示正是建议用户通过require(sails).Sails构造新实例这与本文所述做法完全一致。仓库的测试代码大量采用了这种多实例模式是最佳实践参考test/benchmarks/sails.load.test.js 中每个基准用例都var sails new Sails()创建独立实例test/benchmarks/sails.request.generic.test.js 通过require(../../lib).constructor获取构造器后(new Sails()).load(...)test/hooks/views/intialize.test.js、test/hooks/views/res.view.test.js 等测试同样如此。如果你需要在load之前监听事件或读取配置可以结合sails.on()实例继承自 EventEmitter使用关于更完整的程序化用法在测试、脚本、定时任务中驱动 Sails可参考 Programmatic Usage 概念文档仓库内路径为docs/concepts/Programmatic Usage/。小结全局变量sails全局变量可通过sails.config.globals.sails关闭关闭后改用 action/helper 的this.sails或请求对象的req._sails访问应用实例核心代码自身也遵循req._sails约定。sails.hooks以 identity 为键的已加载钩子字典identity 默认是去除sails-hook-前缀与 npm 命名空间的小写模块名可通过installedHooks配置调整。sails.io底层 socket.io 服务器实例的原始访问口仅建议迁移遗留代码时谨慎使用日常应优先使用sails.sockets.*与 resourceful pubsub。单例 vs 多实例require(sails)返回进程级单例需要多实例时使用require(sails).constructor配合new Sails()每个实例可用不同配置独立load/lift。赞分享后端【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址https://gitcode.com/gh_mirrors/sa/sails点击查看免费下载相关推荐深入理解 Sails 应用对象sails运行时状态、全局访问与高级用法深入理解 Sails 应用对象 sails 运行时状态、全局访问与高级用法 sails 应用对象是 Sails 框架的核心运行时容器承载了应用加载后的全后端Sails 全局变量禁用指南通过 sails.config.globals 精确控制 sails、models、services、_ 与 asyncSails 全局变量禁用指南通过 sails.config.globals 精确控制 sails 、 models 、 services 、 _ 与 asyn后端Sails 全局变量配置指南深入解析 config/globals.js 与 sails.config.globalsSails 全局变量配置指南深入解析 config/globals.js 与 sails.config.globals config/globals.js 是后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考