I have a MongoDB on a web server and I have a Mean stack web application. Within the MongoDB, I have a bunch of data that I want to pass to my web application. I have looked into options, but I'm a little unsure as to which route to take to make this happen. I have considered using socket.io to set up a listener on my web server to open up a connection with my DB, and then making an API call or direct DB connection to return my data.
I should add that my app is based on the mean.io boilerplate code.
My question is where within my stack do I need to put the socket.io code?
Would it be wise to include the socket.io code at the root of my application or only in the packages/modules that require the data to be passed from my web server to my application?
And finally, is socket.io even the preferred route to take? Is there another method to achieve this that makes more sense such as express.js?
There's no need to use socket.io unless you want real-time constant, persistant streaming of information from your database to your front-end.
First in your express app, connect to the db with https://github.com/mongodb/node-mongodb-native. Then, you can just set up a JSON endpoint route for the data to get sent to. Then the client webpage that needs the data simply sends an XHR request to the JSON page.
EDIT: OP does want to use socket.io.
If you want to use socket.io, you have to include it on both the server and the client.
Server-side:
const express = require('express');
const app = express();
const server = require('http').Server(app);
// socket.io
const io = require('socket.io').listen(server);
// handling socket.io requests
io.on('connection', (socket) => {
log.info('new connection.');
socket.emit('data', {/** whatever data you need to send **/});
socket.on('disconnect', (e) => {
log.info('user disconnected.');
});
});
Client-side:
Be sure to include socket.io in the html file (get it from the website). Then, in your client-side js:
const socket = io();
socket.on('connect', () => {
console.log('connected to server.');
});
socket.on('disconnect', () => {
console.log('disconnected.');
});
socket.on('data', (data) => {
// this is where you receive the data
// do something with your data
});
You should create a route in Express and then, request that route from your angular SPA with an http module, like $http ou Restangular.
Take a look at this article https://scotch.io/tutorials/setting-up-a-mean-stack-single-page-application
Related
I am currently running a NodeJS Application, which is displaying a static HTML page(index.html) served from express.
I have socket.io installed.
The route for the view is http://localhost:3000/ with socket initialized in the script tag.
<script>
var socket = io();
socket.on("connection", function (socket) {
console.log("Client Connected Server");
});
....
When emitting the data from the server(socket.emit('data',{}) the frontend is able to receive the data(socket.on('data')) without any problem all works as intended.
What I am trying is to emit the data from the frontend to backend. As per docs it should be possible to do the same but I am not able to. Is there something I am missing.
I tried ways to emit data back from the frontend to the server to where the socket is first created on the server (index.js) but still no effect.
In a Node JS app, I want my server to be able to send a notification to clients, in some specific cases. Searching the net on the subject, I find Service Workers which seems to be what I need; but I am not totally sure.
Here is why. When I look at various tutorials and videos, it seems like the notifications always somewhat originates from some client. But this is not what I want. It should be the server deciding when and what to send as a notification, not some client. So comes my questions:
Am I misunderstanding the way to use Service Workers?
Is this the right path to have my server send a notification to clients?
If the answer to the last question is NO. Then what is the proper way?
Like Dimitar wrote earlier, you could use socket.io to send messages from the server to the client and vice versa. This can be done as simple as that:
//Server sent message:
io.on('connection', (socket) => {
socket.emit('notificationToClient', 'Message'); //message sent from server to client
});
});
//Client receives the message:
const socket = io.connect('http://localhost:3000');
socket.on('notificationToClient', (data) => { //received message
console.log(data);
});
The websocket API is a little less confusing than socket.io but IMO, I'd go with socket.io since it already deals with a lot of the heavy lifting like re-connecting, custom namespaces, rooms etc. There are several fantastic udemy courses on socket.io.
See the socket.io documentation here: https://socket.io/docs/
Update 5/9/2020:
Michel - Since you asked about how to implement Socket.io in your code I'll give you an example of how I implemented this technology in my most recent project. I was working on a web app that connects to ELK Alarm systems and is able to arm/disarm these systems as well as receive sensor input (chime signals) at any remote location. The backend is Node.js and the UI is React.
//client side code
import React, { Component, Suspense } from 'react';
import panels from "./panels.js"
const socketConnection = io("http://localhost:5000"); //Socket.io
function App() {
function handleClick(panel) {
socketConnection.emit("panelData", panel); //Socket.io - sends the connection data for the ELK alarm panel to the express server
socketConnection.on('data', (data) => { //Socket.io - receives data from the server.
//does something with the data
})
}
}
//server side code
const express = require('express');
const elkClient = require('elk-client');
const app = express();
const server = app.listen('5000', () => {
console.log('------Server Running on 5000---------');
});
let io = new sio(server);
io.on("connection", (socket) => { //boilerplate code - establishes the "handshake" with the client.
socket.on("panelData", async (msg) => { //receives the ELK connection parameters from the client. See client side code
const client = new ElkClient({
connection: {
site: msg.name,
host: msg.host,
}
})
await client.connect();
client.on("message", (elkMessage) => { // This is NOT Socket.io - server is listening for emitted data from the alarm system - beam breaks, alarms, arm/disarm etc. [See event emitter][2]
if(elkMessage.messageType == 'A' && elkMessage.subMessageType == 'S') {
const armingStatusReport = {elkMessage};
socket.emit("data", armingStatusReport); //Socket.io - emits the received data to the client.
}
})
I tried to simplify the code above to hit the point. The server is using the connection parameters that it receives from the client to connect to a remote alarm system. The server then waits and listens for incoming data with client.on()(event emitter - not socket.io). As the data is received, I'm using Socket.io to send the received data back to the client with socket.emit(); Due to the nature of how alarm systems work, data is sent event driven so the fetch api wouldn't really fit the bill but socket.io (or websockets) does.
Let me know if I can help with anything else. With this recent project, I have spent the last few months EXTENSIVELY dealing with socket.io, including namespaces, rooms etc. I also had to create a real-time monitoring app for performance management for my server utilizing socket.io since I implemented clustering. Feel free to contact me anytime!
The answer is WebSockets.
Check out Socket.IO. It will give you the possibility of receiving live notifications on the client and you'll have complete server control on them.
What about using twilio library to manage your notification job .twilio library
Is it possible to use console.log() in the backend (I am using express) to output things in the frontend.
for example:
const express = require('express');
const app = express();
client.console.log('Hi');
How would I do it?
Thanks.
There is no built-in support for a server to cause something to show in the client console. I'm not sure what the actual use case for that is since the console is typically a debugging aid, not an actual end-user thing.
In any case, if you want to do that, you would have to have cooperating code on both the client and the server and then how that code works depends upon the context in which you want to put the info in the console.
From a page load
From a page load, the server could embed a small script in the page that would output into the browser console when the page loads and runs.
From an Ajax call
Here, you could include a property in some returned JSON that contains the desired console message and then the client code making the ajax call would have to grab that property and call console.log() with it.
From any random time on the server
If you're not in the context of an existing request from the browser or web page Javascript (as in the previous two points), then you would need some push channel connected between the web page and the server such as a webSocket connection, a socket.io connection or a SSE connection. Then, you could send a message to the client and the client would need some code listening for those incoming messages and then display them in the local console upon receiving them.
try it:
The 'send' method of 'res' object of Express, is one of so many ways to send a response to client in the request event.
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('Hello world!')
})
There is no support as jfriend00 said, but there is a way to go around this.
So lets say the user requests /test
You want to displayin his console Hello World
So you do:
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('<script>console.log(Hello world!)</script>')
})
And that acts as a full client console log. There ya go. (Single Time)
Or setup socket.io as jfriend said in his post if you want to constantly post console messages (multiple times).
I'm using Using Firebase and Node.js I'm trying to make a real-time list, see code below:
router.get('/', (req, res) => {
db.ref('contacts').on('value', (snapshot) => {
const data = snapshot.val();
console.log(data);
res.render('index', { contacts: data });
});
});
but is giving me this error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Your code is trying to send multiple responses from an Express route. The error message is telling you that's not possible. Once you call res.render(), you are declaring the full response to be sent to the client, and that's all you can send. The client will have to make another request to get an update.
If you want to keep a socket open to the client to send updates over time, you're going to need a websocket or some other way to keep the connection open. express-ws is one thing to try on the backend. Note that this will not work with Cloud Functions and probably other serverless providers.
I'm using Mongoose to store the chat between different registered users, at the current implementation they can retrieve chat logs if they refresh the page! which is not identical to be a real-time solution.
How to use socket.io() to act as sender/receiver for many users.
I followed
https://socket.io/get-started/chat/
and
https://medium.freecodecamp.org/simple-chat-application-in-node-js-using-express-mongoose-and-socket-io-ee62d94f5804
But both, they assume the same port for the same user.
It is always a better idea to refer to the official API documentation.
https://socket.io/docs/client-api/
In your case, you need to create a separate socket for a separate private chat
//Join PrivateRoom - client
var socket = io.connect('http://localhost');
socket.emit('joinprivate', {email: user1#example.com});
//Server
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.on('joinprivate', function (data) {
socket.join(data.email); // We are using room of socket io
});
});
More examples:
How to send a message to a particular client with socket.io