Using Jquery in Node Js - javascript

I am trying to use JQuery in my Node Js Code but it is not working.
Please see my below Node JS code.
var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function (request, response) {
response.writeHeader(200, {
"Content-Type": "text/html"
});
response.write(html);
response.end();
}).listen(8080);
});
require("jsdom").env("", function (err, window) {
if (err) {
console.error(err);
return;
}
var $ = require("jquery")(window);
$('#div1').append('<div>dd</div>');
});
My Index file is coming properly. There is a Div which has div1 Id in my Index.html but I couldn't append new div into my index.html.
What is the problem? Is there any problem in my code?
In addition, if I define var $ in top of the code and move the $('#div1').append('<div>dd</div>'); code out of the brackets such as
});
$('#div1').append('<div>dd</div>');
var db = require("./db_select");
Node JS throwing an error such as: TypeError: $ is not a function
How can I define a global $ ?
I've changed my code as below because I'm anticipating that it can be a sync problem.
var runHtml = function () {
this.load = function () {
var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
console.log('Node Js is working');
http.createServer(function (request, response) {
response.writeHeader(200, {
"Content-Type": "text/html"
});
response.write(html);
response.end();
}).listen(8080);
});
};
this.createjson = function () {
require("jsdom").env("", function (err, window) {
if (err) {
console.error(err);
return;
}
var $ = require("jquery")(window);
$('#div1').append('<div>dd</div>');
});
};
if (this instanceof runHtml) {
return this.runHtml;
} else {
return new runHtml();
}
};
var runit = new runHtml();
runit.load().createjson();
However, when I run this code, I'm getting an error from the terminal such as: TypeError: Cannot read property 'createjson' of undefined
Why am I getting this error?
As you can see I have a createjson function and I'm trying to call it after load function as using javascript chaning!

The terminal actually gave it away. When you get the error TypeError: Cannot read property 'createjson' of undefined that tells you where to look. In your code, there is a thing, which has a property of creaetejson, that, at runtime, is undefined.
In your last code snippet, at the end, you have a line that goes runit.load().createjson();. This is a line that has a thing (the call to the load method) that has a property called createjson. Looking at the rest of that code snippet, we see that load is a method of runit, which is defined by the line above it var runit = new runHtml();. If we checkout the runHTML function, we find that it has a method called load. In this method, there is no return statement, so it returns undefined by default.
Returning to the line runit.load().createjson();, we can now see how it is evaluated: runit is a functional style class and load is a method on runit, which returns undefined. You called the load method on the runit class, which means that the line (aside from what it does in the load function) is the same as undefined.createjson().
Now, in regards to solving the problem, there are a number of different ways to go.
The simplest way may be to simply return the object from the load method. If you go that route, I suggest you beef up your knowledge of the keyword this. You may also want to look into the keywords async and await.
Happy Coding

Related

Node javascript require js file?

I just want to load the content of a js file into my variable ! but it's returning me an object ? how can i achieve that ?
server.js
const file = require("./server/file.js");
ctx.body = `${file}`; // Should return "(function () { console.log("ok");})";
//file.js
(function () {
console.log("ok");
});
Use file reader for this, check out this documentation NodeJs website
var fs = require('fs');
fs.readFile('./server/file.js', 'utf8', function(err, data) {
if (err) throw err;
const fileContent = data;
console.log(fileContent);
});
Any CommonJS module will export the value of module.exports which defaults to being an empty object (i.e. what you are seeing).
Your module doesn't explicitly export anything.
It has a function expression that you do nothing with (you don't call it, you don't assign it anywhere, you don't pass it anywhere: it is completely pointless).
If you want to export the function then you need to do so explicitly.
function myFunction() {
console.log("ok");
}
module.exports = myFunction;

Modules with Arguments NodeJS

I have two files, home.js and module.js in the same directory.
What I'm trying to do is, I'm trying to pass the variable named directory as I call the function I exported from module.js.
It gives me this error:
binding.readdir(pathModule._makeLong(path), req);
Type error: path must be a string.
What I'm trying to figure out is, I've passed the directory variable which is process.argv[2] (contains the path) from home.js as I call the function in module.js that requires the same argument (path).
home.js
var fs = require('fs');
var path = require('path');
var module = require('./module.js');
var directory = process.argv[2];
var extensionRequired = process.argv[3];
function printList(err, data) {
if(err) return err;
list.forEach(function (file) {
if(path.extname(file) === '.' + extensionRequired) {
console.log(file);
}
});
}
module(directory, extensionRequired, printList);
module.js
var fs = require('fs');
var path = require('path');
module.exports = function (directory, extensionRequired, callBack) {
fs.readdir(directory, function(err, list) {
if(err) return err;
callBack(err, list)
});
}
I think you made a mistake, and forgot to rename the list variable:
function printList(err, data) {
if(err) return err;
// Here list => data
data.forEach(function (file) {
if(path.extname(file) === '.' + extensionRequired) {
console.log(file);
}
});
}
In your callback-method, named printList, you set the second argument as data. If you want to access the second argument's value again, you have to use data in your code or reassign it to another variable.
Your method may then look like this:
function printList(err, data) {
if (err) return err;
data.forEach(function (file) {
if(path.extname(file) === '.' + extensionRequired) {
console.log(file);
}
});
}
Additionally, I see two more problems with your code:
In module.js, you're requiring the parameter extensionRequired. If you look closely, you'll find, that it isn't even used in this method. This isn't really an error, but would in my opinion be seen as inelegant. Rather pass it trough to the printList as an additional argument (more the node-typical way IMHO) or use it as a global-scope variable as you are currently doing anyway.
In your module.exports-anonymous function from module.js, you are using if (err) return err;. I'd highly recommend you to not do such a thing. Because this is an asynchronous method, you can't really return something, as the return-statement might actually be executed after you called this method. Instead, pass your error as the first argument of the callback. If there is no error, pass null instead, so you can easily figure out if something unexpected happened. Always check that!
Your module.js could then look something like this:
var fs = require('fs');
var path = require('path');
module.exports = function (directory, callback) {
fs.readdir(directory, function(err, list) {
if (err)
// Error happened, pass it to the callback
callback(err);
else
// Everything ran smooth, send null as the error (no error)
// and the list as the second argument.
callback(null, list)
});
}
Your home.js should then be changed accordingly:
var fs = require('fs');
var path = require('path');
var module = require('./module.js');
var directory = process.argv[2];
var extensionRequired = process.argv[3];
function printList(err, data) {
if (err) {
console.error("An error occurred:", err);
// Exit with an error-code of one to
// tell failure to the calling process and
// prevent printing the probably 'undefined' data-variable
process.exit(1);
}
data.forEach(function (file) {
if(path.extname(file) === '.' + extensionRequired) {
console.log(file);
}
});
}
// extensionRequired removed, as it is not needed
module(directory, printList);

Nested JSON.parse errors and JS object traversal errors not trapped by JS try/catch, crashes server

I have this POST route handler in Express. I am concerned that using one large try/catch block does not correctly trap all errors that occur inside it.
Inside the only try/catch block below, I try to access a nested native JS property - that being - parsed.template.list.push(listItem);
So I am trying to push an object onto an array in nested property. If template doesn't exist, it will cause a runtime error, but this isn't trapped by the try/catch, the server just quite literally halts, and no JSON response is sent.
Is there a way to improve my code - do I need to put a myriad of try/catches in my code to try to absent-mindedly safeguard everything?
POST: function (req, res, next) {
var incidentId = req.body.incident_id;
if (incidentId) {
csDataHelper.getAccountNumWithIncidentCorrelationID(incidentId, function (err, response, body) {
if (err) {
return res.json({error: err.toString()});
}
try { // big try/catch starts here
var body = JSON.parse(body);
var result = csDataHelper.parseInfoFromCSResponse(body);
if (!(result instanceof Error)) {
var accountNum = result.accountNum;
var homePhone = result.homePhone;
var altPhone = result.altPhone;
var absPath = path.resolve(nconf.get('globalRoot').concat('/json_response_templates/pay_by_phone.json'));
fs.readFile(absPath, 'utf8', function (err, jsonTemplate) {
if (err) {
res.json({'error': err.toString()});
}
else {
var str = jsonTemplate.replace('${accountNumber}', accountNum).replace('${incidentId}', incidentId);
var parsed = JSON.parse(jsonTemplate);
if (homePhone) {
var listItem = {
"label": homePhone,
};
parsed.template.list.push(listItem);
}
if (altPhone) {
var listItem = {
"label": altPhone,
};
parsed.template.list.push(listItem);
}
res.json(parsed);
}
});
}
else {
return res.send({error: 'no accountNumber sent to Baymax from Contextstore ->' + result});
}
}
catch (err) {
return res.json({error: err.toString()});
}
});
}
else {
res.send({error: 'null/empty incident_id posted to Baymax'});
}
}
}
When certain code inside the try/catch experiences an error, the error is not trapped by the try/catch block. SPECIFICALLY, I know that in some cases "parsed.template.list.push(listItem);" should actually be "parsed.list.push(listItem);", depending on the nature of the JSON coming at me.
In other words, in JS, do I need to use nested try/catches when using nested JSON.parse calls or nested JS object property retrievals?
Frankly, this is quite dangerous and of all the things I have seen in Node.js, parsing JSON and traversing native JS objects poses some of the biggest threats to server uptime.
How to combat this?
The reason it's crashing on parsed.template.list.push(listItem) is because that line is inside a callback for an asynchronous function call. try-catch blocks do not magically cover callbacks.
So your best bet at the moment is to either add a try-catch inside the callback or add a conditional like if (parsed.template && parsed.template.list) { .. }.

Node.js request download file sometimes empty or no existing

I'm writing a downloader with node.js and the request module. Using the stream syntax I'm doing
var r = request(url).pipe(fs.createWriteStream(targetPath));
r.on('error', function(err) { console.log(err); });
r.on('finish', cb);
to download the file, save it and call the callback. However, in almost 50% of the cases the file is either empty or not created at all. No error event is emitted. It seems like the finish event is triggered even though the file wasn't (completely) written yet.
Context: The whole thing is wrapped into async.each calls.
Any clues? Thanks!
You need to close the file before accessing it:
var file = fs.createWriteStream(targetPath);
var r = request(url).pipe(file);
r.on('error', function(err) { console.log(err); });
r.on('finish', function() { file.close(cb) });
Incidentally, if the url replies with any http error (such as a 404 not found), that won't trigger the 'error' event, so you should probably check that separately:
function handleFailure(err) { console.log(err); };
var file = fs.createWriteStream(targetPath);
request(url, function(error, response) {
if (response.statusCode != 200) {
console.log("oops, got a " + response.statusCode);
return
}
// close is async, and you have to wait until close completes otherwise
// you'll (very rarely) not be able to access the file in the callback.
file.on('finish', function() { file.close(cb) });
response.pipe(file).on('error', handleFailure)
file.on('error', handleFailure)
}).on('error', handleFailure);

Node.js Variable scope

I have a http server setup which basically needs to look up stuff in the database.
Here is the code snippet :
var sys = require('sys');
var Client = require('mysql').Client;
var client = new Client();
client.host = '_';
client.user = '_';
client.password = '_';
client.database = '_';
var http = require('http');
http.createServer(function(req, res) {
req.on('end', function() {
client.connect(function(error, results) {
if (error) {
console.log('Connection Error:');
return;
}
ClientConnectionReady(client);
});
ClientConnectionReady = function(client) {
var final = '';
client.query('select * from table', function selectCb(error, result, fields) {
if (error) {
console.log('ERROR');
client.end();
return;
}
final += "{" + JSON.stringify(result);
});
client.query("SELECT COUNT(*) from table", function selectCb(error, result, fields) {
if (error) {
console.log('ERROR');
client.end();
return;
}
final += "," + JSON.stringify(result) + "}";
});
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.write(final);
res.end();
client.end();
};
});
}).listen(8007, "127.0.0.1");
  
If I print the values of the variable 'final' at the places where I assign them, I see valid values, but at the lines when I do 'res.write(final)', final is still blank.
How do I make this work and why is this failing?? Thanks for the help, I am new to node.js
The Node.js environment is asynchronous. Those statements that modify "final" are inside callbacks that are executed only when the database operations finish. The code immediately after the initiation of the database operations, where you write the result, are executed long before those callbacks run.
You've almost stumbled upon the answer to the problem already: you must not write the result until the operations are finished, which you know will be the case inside the callbacks. If you must wait for both to finish (seems like you do), then you can do something like keep a counter in the outer scope. Each callback can increment the counter, and call the same result-writer function only when the counter indicates that both callbacks are complete. (I have the idea that the Node runtime has a fancier way of doing that sort of thing, but I'm not that familiar with it. In a simple case like this, keeping something like a counter is easy enough to do.)
Also, an unrelated note: that "ClientConnectionReady" variable should probably either be written as a function definition:
function ClientConnectionReady(client) {
// ...
}
or else it should be declared with var. (I'm a little surprised in fact that it's not throwing an error, but again I'm not that familiar with Node.js.)
By the looks of it, you are trying to write final before it is ever assigned a value.
I'm assuming that client.query is asynchronous. Given that, the callback function is most likely being called after the res.writeHead and res.write lines. What you need to do is put other calls and the client.write* lines within the first callback.
This should give you an idea (didn't check if it compiles)
ClientConnectionReady = function(client)
{
var final = '';
//Get the rows
client.query('select * from table',
function selectCb(error, result, fields)
{
if (error)
{
console.log('ERROR');
client.end();
return;
}
final+="{"+JSON.stringify(result);
//Get the count query
client.query("SELECT COUNT(*) from table",
function selectCb(error, result, fields)
{
if (error)
{
console.log('ERROR');
client.end();
return;
}
final+=","+JSON.stringify(result)+"}";
//Return the final results to the client now
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(final);
res.end();
client.end();
});
});
};
What this does is first gets the rows. In that callback, it then gets the count. Finally, when that works, it sends the data to the client within the count callback.

Categories

Resources