Nodejs: How to keep an updated list accessible between files

Asked

Viewed 135 times

2

In a Nodejs application with Express/EJS, I need to keep an updated list and I would like that whenever the user accesses my root route, that is the INDEX page, he could see this updated list. To summarize I put together the script below, which is responsible for updating the client list (but it doesn’t have to be the way I put it together...):

Client list update script:

// clients_list.js ============================================================
const tls = require('tls');

var clients = [];// Essa será a minha lista de clientes <<<===========
var aa = [{name: "aaaaaaaa"}, {name: "bbbbbbbb"}];

const server = tls.createServer(options, (myObj) => {

   myObj.on('beginEvent', (anotherObj) => {
      // Adiciona um cliente a cada evento
      clients.push(anotherObj);
   })

   myObj.on('endEvent', (anotherObj) => {
      // Remove um cliente a cada evento
      clients.splice(clientes.indexOf(anotherObj), 1);      
   })

});

module.exports = { server, clients, aa };

EXPRESS "app.js" file, where I want the list to be accessible and always updated:

// app.js do EXPRESS ==========================================================

const app = express();
// vários outros requires...
const indexRouter = require('./routes/index');

// Importação do servidor "serverCLIENTS.server" e da lista "serverCLIENTS.clients"
const serverCLIENTS = require('./clients_list'); 

// um monte de coisas....


// Minha rota raiz
app.use('/', indexRouter); // <<<========= PRETENDO QUE ESTA ROTA EXIBA A LISTA "serverCLIENTS.clients"


// um monte de coisas....

module.exports = app;

QUESTION: How do I make this list "clients" remain visible and up to date in my application?

Will the way is to make one middleware of this my script clients_list.js?

  • As lists are passed by Javascript reference, any file you require from it will be accessing the same list. If your app js. require from the list, and add an item, this item will also appear for another file that does require. But there is a point to be considered when using this method: If your list is kept in a variable, it will only exist while the server is standing. When restarting the server, the list that was in volatile memory will be lost. Was that the question? Sorry it was not very clear.

  • My doubt is the same, but I didn’t understand how to make this list "updateable" everywhere I do the require. For example, in the app.js, I can access the client list through indexRouter.clients, OK! However, as I make that same list visible also in the file index.js for example. If I make a require inside the page index.js, a new instance of the list will be created and not a note to the existing list in app.js. Do you agree? I don’t know if I can make myself understood now, but can you help me I am very grateful.

  • 1

    No, a new instance will not be created. clients in index.js will be the same instance of clients in clients_list.js.

  • I think there’s something else I’m not seeing... at the beginning of client_list.js, if for example I include var aa = [{name: "aaaaaaaa"}, {name: "bbbbbbbb"}];, i can list this data on the index page. However, the variable clients of client_list.js is updated in an asynchronous process, ie when I run the require clients_list.js in the index.js for example, this client list does not yet have any item. Over time it is being incremented. Only when I update the index page, no item is shown.

  • I edited the script and include the variable var aa = [{name: "Aaaaaaaaaa"}, {name: "bbbbbbbb"}]; at first. This data I can list on the index page. Already the variable clients, even after including items in it I can not list them in the index, because it will only be updated after the server is created through the line const server = tls.createServer(options..... After this piece of code is executed I will no longer be able to list the contents of the variable because the index page has already been loaded. I think that’s the problem that keeps me from seeing the updated list.

  • @user140828, I managed to make it work without changing anything of the code I posted initially, but I could not find the problem that prevented it from working before. But as you said, really Nodejs DOES NOT CREATE another instance of the Object when doing require of the same JS file in multiple scripts (it’s in the documentation included), as long as an OBJECT is exported, as I did. If a FUNCTION is exported, then the story is different. Well at least it served to me to study a lot more things. Thank you!

Show 1 more comment

1 answer

0

If you want to share a property between several modules of your application, one way is to use the Singleton Pattern applied to Node, defining a module that contains the single instance, which will be consumed and changed by several other modules.

e. g. :

Defining a Singleton with an array:

// singleton.js
const names = ['Joana', 'Jorge'];

module.exports.names = names;

consuming it in module A:

// singletonconsumer.js
const names = require('./singleton').names;

function seeNames() {
    console.log(names);
}

module.exports.seeNames = seeNames;

Consuming and changing in module B:

// index.js 
const names = require('./singleton').names;
const seeNames = require('./singletonconsumer').seeNames;

print();

names.push('fernanda');

print();

function print() {
    console.log(names);
    seeNames();
}

The result of the print:

printando antes e depois da alteração

Example running: https://repl.it/@spartanroger/Node-Patterns

Link about Twitter with Node : Rising stack Nodejs and Design Patterns

  • Pretty cool! The problem is that my module clients_list.js it takes a while to load the array variable clients and it’s an asynchronous process like almost everything else in Javascript. So when I do a const serverCLIENTS = require('./clients_list');, the imported variable serverCLIENTS.clients is still empty because there was no time to be populated. So I need some parallel process that updates the variable... I need that whenever the user accesses the root route, the current content of the variable is displayed serverCLIENTS.clients.

  • Actually, the Node process is asynchronous and this can give problems. Two alternatives there, either use a lib to make the Node synchronous, like Sync, or not send the list directly on the root route, but rather expose an endpoint with this information and the application make an AJAX call, which is also asynchronous! What do you think?

  • To tell you the truth, I don’t have an opinion. I’m inexperienced in Javascript/Nodejs and I don’t know how to do any of that. I’m now studying the use of Promisses and Bluebird to see if it’s possible to adapt my code, but I also don’t have an opinion on it. If you have anything in there about this or even an example of your suggestions it would be helpful. Thank you for your attention.

  • Got it, no problem. I recommend that the root page make an HTTP request for another route and thus get the list separately. So you can treat information loading asynchronously on the page, with loading and everything. Now if you want the page to be updated when the list is updated, then it would recommend using web sockets. https://www.npmjs.com/package/websocket

  • On the Client side I have an Iot device that requests via socket, as you well noted. I have tried unsuccessfully to use this Websocket package with my application, which needs to have secure certified communication. I couldn’t make it work without the certificate to speak the truth. Anyway, the socket communication as I did already works. What I don’t know, which would be the first step, is to read the variable clients after it has been filled with the customer list. In a second moment, perhaps, I may need to update the list in real time.

  • On the question of doing with a separate route request, it might even work for a page where the data will be displayed, but I don’t know how this would work in a script where I’m not making requests, for example, if I wanted to read the same list clients inside the script app.js.

  • Being a solution for Iot I have no expertise, I don’t know if Webhook or Websockets are ideal, since the device doesn’t have much bandwidth for communication...maybe use an Iot-specific protocol for communication between these scripts...

  • Yes, but communication is fine. This is already overcome, despite the few features offered by the processor of these types of hardware. I implemented a proprietary communication model in the simplest possible way, only with a socket and a protocol of my own. There are many things ready, such as the MQTT protocol, supported by most hardware, yet I would run into the same problem, which is on the server side. But thank you for your attention.

  • studying about the use of Singleton I ended up finding this topic that caught my attention by the amount of information and warnings about the use of this type of resource. See here: https://stackoverflow.com/questions/13179109/singleton-pattern-in-nodejs-is-it-needed

  • As was said in the link you sent, if an object is exported as in the example I posted, works well. If a function is exported it can cause problems with the Node cache.

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.