Node.js函数式编程场景下如何处理可复用的connection连接对象?
函数式编程下Socket连接复用方案
直接把连接设为全局变量的做法虽然简单,但存在状态不可控、多连接场景无法隔离、副作用隐式存在的问题,不符合函数式编程的设计原则,以下是几种更合理的实现方案:
依赖注入
把连接作为参数直接传入业务函数,连接的创建、复用、销毁全部交由上层逻辑统一管理,业务函数本身不需要感知连接的生命周期,全程无副作用。
代码示例:
// 业务函数仅负责逻辑实现,连接由外部传入 function doSomething(connection, argument2) { return connection.doSomething(); } // 上层统一初始化连接 const sharedConnection = createConnection(argument1); // 多次调用复用同一个连接 const result1 = doSomething(sharedConnection, arg2_1); const result2 = doSomething(sharedConnection, arg2_2); // 业务结束后统一销毁连接 sharedConnection.close();
这种方案实现最简单,还天然支持多连接隔离,比如需要同时连两个不同的服务时,只要传入不同的连接实例即可,业务逻辑完全不需要修改。
闭包工厂封装
如果不想每次调用业务函数都传连接,可以用工厂函数把连接封在闭包作用域里,对外只暴露绑定好连接的业务方法,既不会污染全局作用域,也能隐藏连接的实现细节。
代码示例:
// 工厂函数初始化一次即可生成绑定了固定连接的服务实例 function createService(connectionConfig) { const connection = createConnection(connectionConfig); return { doSomething: (argument2) => connection.doSomething(), close: () => connection.close() }; } // 全局只需要初始化一次 const service = createService(argument1); // 直接调用业务方法即可复用连接 const result1 = service.doSomething(arg2_1); const result2 = service.doSomething(arg2_2); // 用完销毁 service.close();
Reader Monad(严格纯函数场景适用)
如果你的项目严格遵循纯函数规范,不想显式在每个业务函数里传递连接参数,可以用Reader Monad来隐式透传连接上下文,全程保持函数的纯性,适合调用链路长、层层传参太繁琐的场景。
简化实现示例:
const Reader = run => ({ run, map: f => Reader(ctx => f(run(ctx))) }); // 业务函数从Reader上下文中自动获取连接 const doSomething = argument2 => Reader(connection => { return connection.doSomething(); }); // 运行时统一传入连接实例 const sharedConnection = createConnection(argument1); const result1 = doSomething(arg2_1).run(sharedConnection); const result2 = doSomething(arg2_2).run(sharedConnection);
选型建议
普通JS/TS项目优先选择依赖注入或者闭包工厂方案,学习成本低,足够覆盖绝大多数业务场景;如果项目基于纯函数式语言开发,或者已经引入了函数式Monad体系,再考虑使用Reader Monad方案。
内容的提问来源于stack exchange,提问作者Kerim Güney
相关产品推荐
相关产品推荐

