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
});
}
Related
I am building NodeJS code that listens to requests from specific ports and returns a response to it, here is the main code:
module.exports = function (port) {
var fs = require("fs");
var path = require("path");
var express = require('express');
var vhost = require('vhost');
var https = require('https');
var http = require('http');
var bodyParser = require("body-parser");
var normalizedPath = require("path").join(__dirname, "../BlazeData/ssl/");
var options = {
key: fs.readFileSync(normalizedPath + 'spring14.key'),
cert: fs.readFileSync(normalizedPath + 'spring14.cert'),
};
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var normalizedPath = path.join(__dirname, "../WebServices");
fs.readdirSync(normalizedPath).forEach(function(file) {
if (file.indexOf('.js') != -1) {
var url = file.substring(0, file.length - 3);
app.use(vhost(url, require(normalizedPath+"/"+file).app));
console.log( 'Registered Service -> %s:%d', url, port );
}
});
if (port == 80) {
var server = http.createServer(app).listen(port, function(){
console.log("Create HTTP WebServices");
console.log( 'Express server listening on port %d in %s mode', port, app.settings.env );
});
}
if (port == 443) {
var server = https.createServer(options, app).listen(port, function(){
console.log("Create HTTPS WebServices");
console.log( 'Express server listening on port %d in %s mode', port, app.settings.env );
});
}
}
I have another JS file that is used to run the script above, I use
var https1 = require('./clientAuthServer') to initiate the code from above where clientAuthServer.js is the filename of the main code, however it just skips everything from that file.
How would I call module.exports = function (port) from a separate file and give a value to the parameter "port" which the function is using?
When you require your module it returns a function (the function exported by the module). The function is being assigned to the variable https1, so you simply need to call that function because right now it's just being stored.
The simplest way would be for your require statement to look something like this:
const https1 = require("./clientAuthServer")(parameter);
Where parameter is just whatever value you want to pass to the function.
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
Stuck on my first attempt at a basic app. Scraper.js scrapes a URL and writes the returned array to the document obj when run alone in console, so that part works. Now all I want is an Express server to run the script whenever I open localhost:3000 but not sure how to do so.
|node_modules
|package.json
|public
|-index.html (boilerplate HTML. Not importing anything)
|src
|-scraper.js
|index.js
index.js:
var scraperjs = require('scraperjs');
var express = require('express');
var app = express()
app.use(express.static(__dirname + '/public'));
app.listen(3000);
--
scraper.js:
scraperjs.StaticScraper.create('https://examplesite.com/')
.scrape(function($) {
return $(".entry-content p").map(function() {
var content = $(this).html();
return content
}
}).get();
})
.then(function(data) {
... // eventually will write the items returned from the data array to div's
}
});
You need to export the scraperjs function using module.exports = functionName() as the last line in scraper.js.
Your require in index.js needs to factor in the path location for scraper.js. So:
var scraperjs = require('./src/scraperjs');
Here is a one that i've coded with promises, and also using a global variable which is daNews
var scraperjs = require('scraperjs');
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
var url = 'https://news.ycombinator.com/';
var daNews;
function myScraper(){
return new Promise((resolve, reject) => {
scraperjs.StaticScraper.create(url)
.scrape(function($) {
return $(".title a").map(function() {
return $(this).text();
}).get();
})
.then(function(news) {
daNews = news;
resolve('done');
})
});
}
app.get('/', function(req, res){
async function m1(){
var x = await myScraper();
if(x == 'done'){
res.send(daNews);
}else{
console.log('err');
}
}
m1();
})
app.listen(3000);
I have put the server setting script into a separate js file called server.js. My problem is that I don't know how to get the value of cookie_key from the express middleware function and pass it back to the index.js file.
server.js:
var express = require('express'),
app = express(),
http = require('http').createServer(app),
cookie = cookieParser = require('cookie-parser'),
url = require('url');
module.exports = {
use_app : function(){
app.use(function (req, res, next) {
var cacheTime = 86400000*7; // 7 days
if (!res.getHeader('Cache-Control'))
res.setHeader('Cache-Control', 'public, max-age=' + (cacheTime / 1000));
next();
});
},
get_app : function(callback){
app.use(cookieParser());
app.get('/id/:tagId', function(req, res){ // parse the url parameter to get the file name
function getkey(err,data){ // get users' session cookie
var cookie_key;
if(err)
{
callback(err);
}
cookie_key = req.cookies["session"];
callback(cookie_key);
}
var filename = req.param("tagId");
res.sendFile(filename+'.html');
});
}
}
index.js:
var server = require('./server'),
server.use_app();
server.get_app(); // how to get the cookie_key when calling this function?
console.log(show_cookie_key_from the module);
if(cookie_key !== undefined)
{
// do something
}
I tried to write a callback function to fetch the cookie key but I don't think it's working.
Update from A.B's answer:
var server = require('./server');
server.use_app();
server.get_app(function(cookie){
if(cookie !== undefined)
{
// do something
}
});
But I still think there is something strange about this setup, what exactly are you trying to accomplish with splitting the app up like this?
Since you are using callback function and that is being poplulated with cookie value , you can get this like following:
var server = require('./server');
server.use_app();
server.get_app(function(cookie){
cookie_key= cookie
if(cookie_key !== undefined)
{
// do something
}
});
The argument of require(...) in node.js is a filename. If I had a module source code in a string code, could I somehow call require(code) and load functions from that string?
I put this into a function for reuse. It creates a file in the os temp directory based on a random hash, requires it and then deletes it.
var fs = require('fs'),
os = require('os'),
crypto = require('crypto');
function requireString(moduleString) {
var token = crypto.randomBytes(20).toString('hex'),
filename = os.tmpdir() + '/' + token + '.js',
requiredModule = false;
// write, require, delete
fs.writeFileSync(filename, moduleString);
requiredModule = require(filename);
fs.unlinkSync(filename);
return requiredModule;
}
Then you can do:
var carString = "exports.start = function(){ console.log('start'); };",
car = requireString(carString);
console.log("Car:", car);
This is still more of a workaround, but more convenient to use, I think.
A work around could be to write the module source code to a temporary file ./tmp-file.js and then require('./tmp-file'), and then remove the file.
This is probably not optimal because you would either have to block and write the file synchronously, or put everything requiring that module in the callback to the async write.
A working example for async file write (gist - also includes sync file write):
var http = require('http');
var fs = require('fs');
var helloModuleString = "exports.world = function() { return 'Hello World\\n'; }";
fs.writeFile('./hello.js', helloModuleString, function (err) {
if (err) return console.log(err);
var hello = require('./hello');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(hello.world());
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
});
Results in:
$ curl 127.0.0.1:1337
> Hello World