如何从Node.js

时间:2017-02-27 14:02:36

标签: javascript node.js express amd microservices

我有两个一起运行的节点应用/服务, 主应用 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);
}

在主模块中我放了这个代码,我想通过在运行时以某种方式注入它来解耦它?例子将非常有用......

4 个答案:

答案 0 :(得分:4)

您可以从其中一个应用创建一个包,然后在另一个应用中引用该包。

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

答案 1 :(得分:3)

您必须使用vm模块才能实现此目的。更多技术信息https://nodejs.org/api/vm.html。让我解释一下如何使用它:

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

    创建新的vm.Script对象会编译代码,但不会运行它。该   编译后的vm.Script可以多次运行。重要的是要   请注意,代码未绑定到任何全局对象;相反,它是   在每次运行之前绑定,仅用于该运行。

    1. 现在,当您要插入或运行此代码时,可以使用script.runInContext API。
    2. 他们的官方文件中的另一个很好的例子:

      '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);
      

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

答案 2 :(得分:1)

有几种方法可以解耦两个应用程序。一种简单的方法是使用 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 ,你也创建了一个新的Socket。可能我要做的只是发送 套接字ID ,然后就像使用它一样:

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

您还可以使用其他解决方案,例如 kafka 而不是zmq,只考虑速度较慢但会保留日志。
希望这可以让你了解如何解决你的问题。

答案 3 :(得分:1)

您可以使用npm链接功能。

链接过程包括两个步骤:

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

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

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