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



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

主应用程序负责在最后显示来自Diffrent应用程序的所有数据。现在,我将第二个应用程序的一些代码放在主应用程序中,现在它可以正常工作,但是我希望将其解耦。我的意思是,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从您想要以后运行的代码中创建编译的JS代码。请参阅官方文档的描述

创建一个新的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);

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

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

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 ,还可以创建一个新的套接字。大概我要做的就是发送套接字ID ,然后像以下方式使用它:

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

您也可以使用另一种解决方案,例如 kafka 而不是ZMQ,只需考虑较慢,但它会保留日志。
希望这可以使您了解如何解决问题。

您可以使用NPM链接功能。

链接过程包括两个步骤:

  1. 通过在模块的根文件夹中运行NPM链接来声明模块为全局链接
  2. 通过在目标文件夹中运行NPM链接
  3. 中的NPM链接,在目标模块中安装链接的模块

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

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

最新更新