如何从Node.js中的不同应用程序注入模块

我有两个节点应用程序/服务一起运行,1.主应用程序2.第二个应用程序

主应用程序负责显示来自不同应用程序的所有数据。 现在我把第二个应用程序的一些代码放在主应用程序中,现在它的工作,但我希望它是分离的。 我的意思是说,secnod应用程序的代码将不会在主应用程序(通过某种方式注入运行时)

像第二个服务注册到主应用程序注入它的代码。 它的代码只是两个模块,是否有可能在nodejs中做到这一点?

const Socket = require('socket.io-client'); const client = require("./config.json"); module.exports = (serviceRegistry, wsSocket) =>{ var ws = null; var consumer = () => { var registration = serviceRegistry.get("tweets"); console.log("Service: " + registration); //Check if service is online if (registration === null) { if (ws != null) { ws.close(); ws = null; console.log("Closed websocket"); } return } var clientName = `ws://localhost:${registration.port}/` if (client.hosted) { clientName = `ws://${client.client}/`; } //Create a websocket to communicate with the client if (ws == null) { console.log("Created"); ws = Socket(clientName, { reconnect: false }); ws.on('connect', () => { console.log("second service is connected"); }); ws.on('tweet', function (data) { wsSocket.emit('tweet', data); }); ws.on('disconnect', () => { console.log("Disconnected from blog-twitter") }); ws.on('error', (err) => { console.log("Error connecting socket: " + err); }); } } //Check service availability setInterval(consumer, 20 * 1000); } 

在主模块中,我把这个代码,我想通过在运行时注入它解耦它? 例子将是非常有用的…

你将不得不使用vm模块来实现这一点。 更多技术信息在这里https://nodejs.org/api/vm.html 。 让我解释一下如何使用这个:

  1. 您可以使用API vm.script从稍后运行的代码创build编译后的js代码。 请参阅官方文档中的说明

创build一个新的vm.Script对象编译代码,但不运行它。 编译后的vm.Script可以多次运行。 注意代码不绑定到任何全局对象是很重要的。 相反,在每次运行之前,它都会受到约束。

  1. 现在当你想要插入或运行这段代码时,你可以使用script.runInContext API。

另外一个很好的例子是他们的官方文件

 'use strict'; const vm = require('vm'); let code = `(function(require) { const http = require('http'); http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\\n'); }).listen(8124); console.log('Server running at http://127.0.0.1:8124/'); })`; vm.runInThisContext(code)(require); 

另一个直接使用js文件的例子:

 var app = fs.readFileSync(__dirname + '/' + 'app.js'); vm.runInThisContext(app); 

您可以将此方法用于您要插入的条件代码。

您可以从一个应用程序创build一个包,然后在另一个应用程序中引用这个包。

https://docs.npmjs.com/getting-started/creating-node-modules

有几种方法可以解耦两个应用程序。 一个简单的方法是用pub / sub模式(如果你不需要响应)。
(现在,如果你有一个非常适合的应用程序,除非你做一些重构,否则很难解耦。)
zeromq提供了很好的pub / sub实现,速度非常快。
例如

 import zmq from "zmq"; socket.connect('tcp://127.0.0.1:5545'); socket.subscribe('sendConfirmation'); socket.on('message', function (topic, message) { // you can get the data from message. // something like: const msg = message.toString('ascii'); const data = JSON.parse(msg); // do some actions. // ..... }); //don't forget to close the socket. process.on('SIGINT', () => { debug("... closing the socket ...."); socket.close(); process.exit(); }); //----------------------------------------- import zmq from "zmq"; socket.bind('tcp://127.0.0.1:5545'); socket.send(['sendConfirmation', someData]); process.on('SIGINT', function() { socket.close(); }); 

这样你可以有两个不同的容器 (docker)为你的模块,只要确保打开相应的端口。
我不明白,为什么你注入wsSocket ,并且你创build一个新的套接字。 也许我会做的只是发送套接字ID ,然后就像使用它:

 const _socketId = "/#" + data.socketId; io.sockets.connected[socketId].send("some message"); 

你也可以使用另一个解决scheme,比如kafka而不是zmq,只是考虑慢一些,但是会保留日志。
希望这可以让你了解如何解决你的问题。

你可以使用npm链接function。

链接过程由两个步骤组成:

  1. 通过在模块的根文件夹中运行npm链接声明模块为全局链接
  2. 通过在目标文件夹中运行npm链接,将链接的模块安装到目标模块(app)中

这工作得很好,除非您的本地模块之一依赖于另一个本地模块。 在这种情况下,链接失败,因为它找不到依赖模块。 为了解决这个问题,需要将依赖模块链接到父模块,然后将父代安装到应用程序中。

https://docs.npmjs.com/cli/link