Node.js- Make array in app.js available in a module - javascript

In my Node app.js, I don't necessary need to have my array openConnections global...but I want it in app.js and accessible by module sse_server.js for the sseStart function. How can I do this?
app.js:
var express = require('express');
var morgan = require('morgan');
var fs = require("fs");
var createDomain = require("domain").create;
var app = express();
app.use(express.static(__dirname + '/app/static/views'));
app.use(express.static(__dirname + '/app/static'));
app.use(express.static(__dirname + '/app/images'));
app.use(express.static(__dirname + '/app'));
var openConnections = [];
var sseStart = require(__dirname + '/app/scripts/sse_server.js');
app.get('/subscribe', sseStart);
var callAllApiAndSave = require('./app/scripts/api_scripts/call_all_api.js');
var db = require(__dirname + '/app/data/db.js');
var mainDomain = new createDomain();
mainDomain.run(function () {
mainDomain.on('error', function() {
console.log('yoyoyoyoyoyoyoyoyoyoyoyoyoyoyo');
});
mainDomain.on('error', function(er) {
console.log('error, but oh well', er.message);
});
db.connectDatabase();
setInterval(callAllApiAndSave, 120000);
var server = app.listen(9000, function() {
console.log('Listening on port %d', server.address().port);
});
});
sse_start.js:
function sseStart(req, res) {
console.log(req);
// set timeout as high as possible
req.socket.setTimeout(Infinity);
// send headers for event-stream connection
// see spec for more information
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
res.write('\n');
// push this res object to our global variable
console.log("Creating SSE connection for " + req.connection.remoteAddress);
openConnections.push(res);
console.log("Total current live connections: " +
openConnections.length);
// When the request is closed, e.g. the browser window
// is closed. We search through the open connections
// array and remove this connection.
req.on("close", function() {
console.log("Closing SSE connection for "
+ req.connection.remoteAddress);
openConnections = openConnections.filter(function(storedRes) {
if (storedRes !== res) {
return storedRes;
}
});
if (!openConnections) openConnections = [];
console.log("Total current live connections: " +
openConnections.length);
});
}
module.exports = sseStart;

Looking at the code you posted openConnections is only used in sse_start.js so why not put it there?
If you really want to share that array between those two files you can just put it in a separate module and require it in app.js and sse_start.js.

Related

how to call URL from local env in Express JS

i have an issue on my code (Weather App using OpenWeahterMap Api) after i tried to move my apiKey and apiUrl to the .env file, i already got this error in the terminal and it's not clear why its happend
here is my code :
const express = require("express");
const https = require("https");
const { restart } = require("nodemon");
const bodyParser = require("body-parser");
const dotenv = require('dotenv');
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'));
// The app will redirect to index.html page
app.get("/", function(req, res){
res.sendFile(__dirname + "/index.html");
})
app.post("/", function(req, res) {
dotenv.config({ path: '/.env' });
require('dotenv').config();
const weatherUrl = process.env.API_URL;
const apiKey = process.env.API_KEY;
const city = req.body.cityName;
const unit = "metric";
const url = weatherUrl + city + "&appid=" + apiKey + "&units=" + unit
// the response will recive the data and will parse the jsonData from the API
// and will print the the current temprerature + description + weather icon
https.get(url, function(response){
response.on("data", function(data){
const weatherData = JSON.parse((data));
const temp = weatherData.main.temp;
const weatherDescription = weatherData.weather[0].description;
const weatherIcon = weatherData.weather[0].icon;
const imageUrl = "http://openweathermap.org/img/wn/" + weatherIcon + "#2x.png"
res.write("<p>The Weather is currently " + weatherDescription + "</p>");
res.write("<h1>The temprerature in" + city + "now is "+ temp + " degress Celcius.</h1>");
res.write("<img src=" + imageUrl + ">");
res.send();
})
})
})
// default port can be change
app.listen(3333, function() {
console.log("Server is running on port 3333");
});
the error message :
Server is running on port 3333
/Programming/JS/WeatherApp/app.js:35
const temp = weatherData.main.temp;
^
TypeError: Cannot read property 'temp' of undefined
i am not sure where is exactly the problem because it's first time i am using Express JS
You need to identify where your path is for your .env file if it is in the same directory as this file then you need to put ./.env if it is in a directory above this one you need to put ../.env or two directories ../../.env. /.env doesn't mean anything
The .env file should also not have semi colons to delimit the end of your keys.

Accessing a functions from a js file thats in a public directory

I have a JS file in a folder called public, which also has my CSS file in it. I'm trying to access a function from the JS file (scripts.js), but am having no luck. I've followed this post (amongst others), but I am still getting an error of Error: Cannot find module './scripts.js'. If anyone can help me out, that would be great.
app.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var request = require("request");
var scripts = require("/scripts.js");
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.use(express.static(__dirname + '/public'));
const apiUrl = "https://api.darksky.net/forecast/";
const apiKey = "XXX";
app.get('/', function(req, res){
res.render("index");
});
app.post('/results', function(req, res){
var lat = req.body.latitude;
var long = req.body.longitude;
request(apiUrl + apiKey + "/" + long + "," + lat, function(error, response, body){
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
var temperature = scripts.converter(data.currently.temperature)
res.render("results", {data: data, temperature: temperature})
} else {
console.log(response.body);
}
});
});
app.get('/results', function(req, res){
res.render("results");
});
app.listen(3000, function(){
console.log("Server has started");
})
scripts.js
module.converter = function(cel) {
var cel = (far - 32) * (5/9);
return cel;
}
exports.data = module;
The path to your module is wrong.
Try var scripts = require("./public/scripts.js"); instead.
You are loading /scripts.js, which is a scripts.js file located at your computers root. To load a file in the current directory, you would do ./scripts.js. In a directory above the current one, it would be ../scripts.js.
If the file is in a directory below the current directory, like in your case, it would be './directoryname/scripts.js'. directoryname being public in your case

If condition directly goes to else always in my case in node js

I am counting list of process and based on process counter trying to perform something but if condition directly goes to ELSE regardless of process counter.
My code :
var express = require('express');
var app = express();
//var sleep = require('sleep');
var counter = 0;
app.get('/', function (req, res) {
res.send(
'<form action="/server" method="POST">' +
' <input type="submit" name="server" value="Run Script" />' +
'</form>');
});
app.get('/counter', function (req, res) {
res.end("Process Counter = " + counter);
});
app.post('/server', function (req, res) {
var fork = require('child_process').fork;
var child = fork('./client');
counter++;
child.on("close", function () { counter --; });
if(counter > 2)
{
app.get('/m', function (req, res) {
res.end("Already multiple process running. = " + counter);
});
}
else
{
app.get('/m', function (req, res) {
res.end("Single or No process running currently = " + counter);
});
}
});
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("app listening at http://%s:%s", host, port)
})
I want to pause / sleep server when process counter reach 10 and then process next queue requests once previous 10 completes so trying to setting like process list of processes in slots like 10,10,10 etc. I will try to manage it once if condition work proper based on counter. Counter seems return correct count.
Few issues with your code. So I created a simple client.js
function test() {
console.log("Running test");
setTimeout(test, 10000);
}
test();
This is nothing but a infinite loop. Then I used app object for the global counter
if (!app.counter)
app.counter = 0;
Next your post becomes below
app.post('/server', function (req, res) {
var fork = require('child_process').fork;
var child = fork('./client');
app.counter++;
child.on("close", function () {
app.counter--;
});
res.send(200, "Current Processes - " + app.counter);
});
Also you were not ending the POST request, so I added res.send(200, "Current Processes - " + app.counter);
Next the /m endpoint is updated as below
app.get('/m', function (req, res) {
if (app.counter > 2) {
res.end("Already multiple process running. = " + app.counter);
}
else {
res.end("Single or No process running currently = " + app.counter);
}
});
So the final code is below
var express = require('express');
var app = express();
//var sleep = require('sleep');
if (!app.counter)
app.counter = 0;
app.get('/', function (req, res) {
res.send(
'<form action="/server" method="POST">' +
' <input type="submit" name="server" value="Run Script" />' +
'</form>');
});
app.get('/counter', function (req, res) {
res.end("Process Counter = " + app.counter);
});
app.get('/m', function (req, res) {
if (app.counter > 2) {
res.end("Already multiple process running. = " + app.counter);
}
else {
res.end("Single or No process running currently = " + app.counter);
}
});
app.post('/server', function (req, res) {
var fork = require('child_process').fork;
var child = fork('./client');
app.counter++;
child.on("close", function () {
app.counter--;
});
res.send(200, "Current Processes - " + app.counter);
});
var server = app.listen(8081, function () {
var host = server.address().address;
var port = server.address().port;
console.log("app listening at http://%s:%s", host, port)
});
If you run the server, it will work fine now
$ curl -X POST http://127.0.0.1:8081/server
Current Processes - 1
$ curl -X POST http://127.0.0.1:8081/server
Current Processes - 2
$ curl -X POST http://127.0.0.1:8081/server
Current Processes - 3
$ curl -X POST http://127.0.0.1:8081/server
Current Processes - 4
And the /m endpoint
$ curl http://127.0.0.1:8081/m
Already multiple process running. = 4
One key thing for testing this is to make sure that you don't launch the script using debugging, you run it. If you look at the child process spawnArgs you will find it as below
And our main process was started as /usr/local/bin/node --inspect-brk=54160 ..../test.js
So the fork tries to launch another process with --inspect-brk=54160, but that port is already busy with our debugger and doesn't let the child process run. So that is the reason you should run it directly instead of debugging the main code

Node.js and Socket.io in Phaser.js not connecting socket.io/?EIO=3&transport=polling

I am able to run my node.js server, my phaser.js game runs but I get no 'connected' console.log when the game runs. I instead get this error message from the client end:
enter image description here
socket.io-1.4.5.js:1 GET http://192.168.128.184:8080/socket.io/?EIO=3&transport=polling&t=LdMR6Ro net::ERR_CONNECTION_REFUSED
SERVER:
var serverPort = 8080;
console.log("Initializing Server.");
var express = require('express');
var connect = require('connect');
var app = express();
var serv = require('http').Server(app); //.createServer(app);
var io = require('socket.io').listen(serv); //(serv,{});
console.log("Starting Server.");
var serveStatic = require('serve-static');
connect().use(serveStatic(__dirname)).listen(serverPort, function(){
console.log('Server running on ' + serverPort + ' !');
});
app.get('/',function(req, res) {
res.sendFile(__dirname + '/index.html');
});
serv.listen(8081);
var SOCKET_LIST = {};
io.on('connection',function(socket){
console.log("A user is connected");
});
io.sockets.on('connection', function(socket){
console.log('Socket connection');
});
CLIENT
var local = "http://" + document.location.host + ":8081";
var socket = io().connect(local);
In your client code you are using io().connect(local) however the correct way to connect using a specified address with your variable is io.connect(local).
Also, document.location.host will include ":8080" if it is a part of the address you used to obtain the page, therefore you need to remove it. You can try something like document.location.host.split(':')[0]

node.js res.write doesn't work

To learn node js i make some exercise but have got a problem, the "res" variable work in index.js but doesn't work in the fs.exists function, why ?. Thanks for your responses.
server.js
var http = require("http");
global.PATH = __dirname;
http.createServer(function(req, res) {
var app = require("./index.js")(req, res);
res.end();
}).listen(8080);
index.js
var url = require("url");
var fs = require("fs");
module.exports = function(req, res){
if(req){
var pathname = url.parse(req.url).pathname.split("/");
pathname.splice(0,1);
var action = pathname[1];
fs.exists(PATH + "/" + pathname[0] + ".js" , function(exist){
var controller;
res.write('doesn\'t work');
if(exist)
{
if(!controller){
controller = require(PATH + "/controllers/" + pathname[0] + ".js" )();
if(controller[action])
controller[action]();
}
}
});
}
}
i don't know why some of you downvoted the question, because for a beginner some asynchronous patterns could be confusing...
first of all you should cache your require-call (as Seth mentioned).
global.PATH = __dirname;
var http = require("http");
var app = require("./index"); //omit .js, you don't need it
then you you index.js you are using fs.exists, which is asynchronous. that means, that the res.end() is called before your callback function inside fs.exists is reached, which means the request/response lifecylcle is over.
you could use fs.existsSync (not recommended!) or provide some callback which you call when done!
2 more things
the if(req) is unneccessary, there is always a request object!
you ALWAYS need to call the callback in your function, to make the response be sent!
server.js:
http.createServer(function(req, res) {
app(req, res, function () {
res.end();
});
}).listen(8080);
index.js:
var url = require("url");
var fs = require("fs");
module.exports = function(req, res, cb) { // see third cb-argument!
var pathname = url.parse(req.url).pathname.split("/");
pathname.splice(0,1);
var action = pathname[1];
fs.exists(PATH + "/" + pathname[0] + ".js" , function(exist){
var controller;
res.write('doesn\'t work');
if(exist)
{
if(!controller){
controller = require(PATH + "/controllers/" + pathname[0] + ".js" )();
if(controller[action])
controller[action]();
}
}
cb(); // whenever you're done call the callback
});
}

Categories