2017-02-27 48 views
10

Mam dwie aplikacje node/usługi, które są uruchomione razem 1. Głównym aplikacji 2. Druga aplikacjaJak wstrzykiwać moduł z różnych aplikacji w node.js

Głównym aplikacja jest odpowiedzialny, aby pokazać wszystko dane z różnych aplikacji na końcu. Teraz umieściłem kod drugiej aplikacji w głównej aplikacji, a teraz działa, ale chcę, aby była odłączona. Chodzi mi o to, że kod aplikacji secnod nie będzie w głównej aplikacji (w jakiś sposób, aby wstrzyknąć go w czasie wykonywania).

podobnie jak druga usługa jest zarejestrowana w głównej aplikacji, wstrzyknąć jej kod. kod to tylko dwa moduły, czy można to zrobić w 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); 
} 

W głównym module umieściłem ten kod i chcę go odłączyć przez wstrzyknięcie go w jakiś sposób w czasie wykonywania? przykład będzie bardzo pomocny ...

+0

Dlaczego nie eksportować swoją drugą aplikację jako moduł, a następnie u można importować go w głównej aplikacji. – Xlee

+0

_ "jakoś wstrzyknąć to w czasie wykonywania" _. To się nazywa 'require()'. – robertklep

+0

Czy możesz wyjaśnić powody, dla których tego chcesz? Jak wspomniano w niektórych odpowiedziach, odsprzężenie jest drogą do osiągnięcia tego. Jeśli nie masz silnego powodu, aby chcieć to zrobić, powiedziałbym, że lepiej jest zabrać się za coś oderwanego - mikro-usługi, pub/sub, kolejka zadań, a nawet po prostu rejestrowanie danych do spożycia przez reportera. – Brian

Odpowiedz

4

Trzeba będzie użyć modułu vm do osiągnięcia tego celu. Więcej informacji technicznych tutaj https://nodejs.org/api/vm.html. Pozwól mi wyjaśnić, jak możesz tego użyć:

  1. Możesz użyć interfejsu API vm.script, aby utworzyć skompilowany kod js z kodu, który chcesz uruchomić później. Zobacz opis z oficjalnej dokumentacji

Tworzenie nowego obiektu vm.Script kompiluje kod, ale go nie uruchamia. Skompilowany vm.Script może być uruchamiany później wiele razy. Ważne jest, aby zauważyć, że kod nie jest powiązany z jakimkolwiek obiektem globalnym; raczej jest on związany przed każdym przebiegiem, tylko dla tego biegu.

  1. Teraz, gdy chcemy wstawić lub uruchomić ten kod, można użyć script.runInContext API.

Innym dobrym przykładem z ich oficjalnej dokumentacji:

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

Innym przykładem wykorzystania js pliku bezpośrednio:

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

Można użyć tej metody dla kodu warunkowego, które chcesz wstawić .

5

Możesz utworzyć pakiet z jednej z aplikacji, a następnie odwołać się do pakietu w innej aplikacji.

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

+0

Dzięki, ale powinno to być oddzielone, tutaj powinieneś umieścić go z wymaganiem .... –

+0

To nie jest takie proste, jak myślisz ... :) –

+0

Zgadzam się, nie jest łatwe. Ale oddzielenie jest dobre. – paqash

2

Istnieje kilka sposobów rozdzielania dwóch aplikacji. Jednym z łatwych sposobów jest wzór pub/sub (w przypadku, gdy nie potrzebujesz odpowiedzi).
(Teraz, jeśli masz aplikację, która jest bardzo para, to będzie bardzo trudne do oddzielenia go chyba zrobić kilka refaktoryzacji.)
zeromq oferuje bardzo dobrą realizację pub/sub i jest bardzo szybki.
np.

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(); 
}); 

W ten sposób można mieć dwa różne pojemniki (Döcker) dla modułów, tylko pamiętaj, aby otworzyć odpowiedni port.
Czego nie rozumiem, to dlaczego wkładasz wsSocket, a także tworzysz nowy Socket. Prawdopodobnie to, co chciałbym zrobić, to wysłać gniazdo id, a potem po prostu używać go jak:

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

Można także użyć innego rozwiązania jak kafka zamiast zmq, po prostu uważają, że jest wolniejszy ale zachowa dzienniki.
Mam nadzieję, że pomoże ci to w rozwiązaniu problemu.

2

Możesz użyć funkcji npm link.

Proces łączący składa się z dwóch etapów:

  1. uznającej moduł jako globalnego łącza poprzez uruchomienie linku npm w folderze głównym modułu
  2. Instalacja połączonych modułów modułu docelowego (APP), uruchamiając npm link w folderze docelowym

Działa to całkiem dobrze, chyba że jeden z twoich lokalnych modułów zależy od innego modułu lokalnego. W takim przypadku połączenie nie działa, ponieważ nie może znaleźć modułu zależnego. Aby rozwiązać ten problem, należy połączyć moduł zależny z modułem nadrzędnym, a następnie zainstalować rodzica w aplikacji.

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