How do i display the javascript error object? - javascript

I am using Node.js and Express web application framework and
mysql package from here
https://www.npmjs.com/package/mysql
here's my Parent.js file .. it's my model file
var db = require('../dbconnection');
var Parent = {
findIfParentMobileNumberExists: function (parentmobilenumber, callback) {
db.query('SELECT parentmobilenumber from parents where parentmobilenumber=?', parentmobilenumber, function (err, rows) {
if (err) {
callback(err, null);
}
if (rows.length < 1) {
console.log("rows length less than 1");
callback(err, null);
}
else if (rows.length !== 0) {
console.log("rows length greater than 1");
callback(null, rows[0].parentmobilenumber);
}
else {
}
});
}
module.exports = Parent;
and here's my registerParent.js file .. this is my route
var express = require('express');
var router = express.Router();
var Parent = require('../models/Parent');
router.post('/', function (req, res, next) {
var countrycode = req.body.countrycode;
var parentmobilenumber = (countrycode) + (req.body.inputMobileNumber);
//remove hyphens from mobile number
var parentmobilenumberwithouthyphens =
parentmobilenumber.replace(/-/g, "");
//remove spaces from mobile number
var parentmobilenumberwithouthyphensandspaces =
parentmobilenumberwithouthyphens.replace(/ /g, '');
Parent.findIfParentMobileNumberExists(parentmobilenumberwithouthyphensandspaces, function (err, parentmobilenumberfromdb) {
if (err) {
res.json({registerErrorMessage: err.message});
}
else {
if (parentmobilenumberwithouthyphensandspaces === parentmobilenumberfromdb) {
console.log(parentmobilenumberfromdb);
}
else {
res.json({registerErrorMessage: 'The Mobile Number does not exist in our database'});
}
}
});
});
if i enter a correct mobile number i get the mobile number displayed in a console.log message .. however when i enter an incorrect mobile number which is not in the database the resulting rows.length is < 1
i get the message
rows length less than 1
but i don't understand when this block runs
if (rows.length < 1) {
console.log("rows length less than 1");
callback(err, null);
}
the err object is never displayed .. i.e this block is never run in the router.post function
if (err){
res.json({registerErrorMessage: err.message});
}
so i want to display the err object correctly first ..
and then i want to display an error message that is readable by end-users
how can i do this ?
i tried reading the documentation here
https://github.com/mysqljs/mysql#error-handling
but i really don't understand how to properly execute callbacks.

You don't start http server with express.
Try to insert code below to start listening:
const app = express();
app.listen( insert port here )

At first, you might want to terminate your logic if an error occurs:
if(err){
return callback(err);
}
Now the error is passed to the client side, where you can catch it and display a message. E.g. (using jquery):
$.ajax({
url:"your/backend",
dataType: "json",
success(res){
if(res.code){
return alert("an error ("+res.code+") occured. Sorry :/");
}
//continue with valid response
}
});
However, you may change your API to be more general, e.g. always return an error property, thats either false or the error object:
on error:
res.json({error:err});
on success:
res.json({error:false,data:"whatever"});
So that you could do this on client side:
$.ajax({
url:"your/backend",
dataType: "json",
success(res){
if(res.error){
return alert("an error ("+res.error.code+") occured. Sorry :/");
}
//continue with valid response
alert(res.data);
}
});

Related

Is there any way to prevent this error in NodeJS?

I'm trying to extract text from pdf file then put it in a string.
I found "pdfReader" and tried to implement it, but I always get an error. At first it begins reading the text normally then when the pdf file ends it stops and block the app.
Code:
var PdfReader = require("pdfreader").PdfReader;
router.get('/adminse', function(req, res, next){
aux='';
new PdfReader().parseFileItems("D:/bureau/VoguelConsulting/Backend/uploads/cv_url_CV_anglais_20191337991.pdf", function(err, item){
if (err)
callback(err);
else if(item==='undefined'){
console.log('erreur');
}
else if(item.text)
{
aux = item.text;
console.log(' aux = ' + aux);
}
else
{
console.log('working');}
});
});
Error:
Use a falsy check with the not operator (!), this will work with undefined and null as well:
else if (!item){
console.log('erreur');
} else if(item.text) {
...

How to repeat a "request" until success? NODEJS

I checked a few thread in StackOverflow, but nothing works for me.
I have this request call and I need it to try to send the request until it succeed (but if it fails, it has to wait at least 3 seconds):
sortingKeywords.sortVerifiedPhrase = function(phrase) {
var URL = "an API URL"+phrase; //<== Obviously that in my program it has an actual API URL
request(URL, function(error, response, body) {
if(!error && response.statusCode == 200) {
var keyword = JSON.parse(body);
if(sortingKeywords.isKeyMeetRequirements(keyword)){ //Check if the data is up to a certain criteria
sortingKeywords.addKeyToKeywordsCollection(keyword); //Adding to the DB
} else {
console.log("doesn't meet rquirement");
}
} else {
console.log(phrase);
console.log("Error: "+ error);
}
});
};
Here's the weird part, if I call the same phrases in a row from the browser, it works almost without errors (it usually states: rate limit time esceeded).
Appreciate your help.
Thanks in advance.
Here is a working program that I've written for this request. It sends the request via a function, if the request fails, it returns error handler and calls the function again.
If the function succeeds the program returns a promise and quits executing.
NOTE: if you enter an invalid url the programs exits right away, that's something that's have to do with request module, which I like to be honest. It lets you know that you have an invalid url. So you must include https:// or http:// in the url
var request = require('request');
var myReq;
//our request function
function sendTheReq(){
myReq = request.get({
url: 'http://www.google.com/',
json: true
}, (err, res, data) => {
if (err) {
console.log('Error:', err)
} else if (res.statusCode !== 200) {
console.log('Status:', res.statusCode)
} else {
// data is already parsed as JSON:
//console.log(data);
}
})
}
sendTheReq();
//promise function
function resolveWhenDone(x) {
return new Promise(resolve => {
myReq.on('end', function(){
resolve(x)
})
myReq.on('error', function(err){
console.log('there was an error: ---Trying again');
sendTheReq(); //sending the request again
f1(); //starting the promise again
})
});
}
//success handler
async function f1() {
var x = await resolveWhenDone(100);
if(x == 100){
console.log("request has been completed");
//handle other stuff
}
}
f1();
On error run this code
setTimeout(function(){}, 3000);
See this https://www.w3schools.com/jsref/met_win_settimeout.asp
Also you can make a code like this
var func1 = function(){};
setTimeout(func1, 3000);

How to stop infinite loop caused by callback in asynchronous function

I have two async functions defined in my program; one of them pings a given IP address(using the net-ping module) and 'returns' (through a callback) whether the ping was successful, and the other creates an SSH connection to a given IP address (using the ssh2 module) and also 'returns' whether the connection was successful or not.
My problem arises when I try to read in IP data from a data.txt file using the readline functionality. I use readline module to read in each line from the file, use the callbacks to call ping and ssh in a blocking fashion, and then place these return values into an array to use later. I've been able to verify that the functions are executed in the order I expect, and that the return values are truly returned.. However, when the program reaches the end of the file - instead of terminating, it just reads the file again, and again, and again.
The SSH function is defined as:
function SSH(ipAdress, callback) {
connection.on('ready', function(err) {
if(err) {
throw err;
returnValue = "ErrorWithReadyConnection";
callback(null, returnValue);
}
//runs the uptime command once we have SSH'd into the machine
connection.exec('uptime', function(err, stream) {
if(err) {
throw err;
returnValue = "ErrorRunningCommandFromSSH";
callback(null, returnValue);
}
else {
stream.on('close', function(code, signal) {
//code holds the response from running 'uptime'
console.log("Stream on close. Code : " + code +
". Signal: " + signal);
connection.end();
returnValue = "success";
callback(null, returnValue);
}).on('data', function(data) {
console.log("STDOUT: " + data);
}).stderr.on('data', function(data) {
console.log("STDERR: " + data);
});
}
});
//Parameters for the SSH connection
}).connect({
host: ip,
port: 22,
username: userName,
privateKey: privateKey,
passphrase: passPhrase
}); //connect
//handle any connection errors done whilst creating a connection
connection.on('error', function(err) {
if(err) {
returnString = "ErrorWaitingForHandshake";
callback(null, returnString);
}
}); //end connect
}
The ping function is defined as:
function pingFunc(ip, callback) {
var returnString;
//Create a ping session, passing the IP of the machine to ping
sessions.pingHost(ip, function(error, target) {
//if error, then examine what type of error has occured
if(error) {
if(error instanceof ping.RequestTimedOutError) {
returnString = "RequestTimedOut";
}
//else, different error - output the error string.
else {
returnString = "Error";
}
} //End error handling
//else, ping was successful
else {
returnString = "Alive";
}
callback(null, returnString);
});
//return returnString;
}
And the code where I call the functions is:
var allMachines = new Array();
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream('data.txt');
});
lineReader.on('line', function(line) {
pingFunc(line, function(err, pingResult) {
SSH(line, function(err, sshResult) {
var machineTemp = [{'ping': pingResult, 'ssh': sshResult }];
allMachines = allMachines.concat(machineTemp);
})
})
}
I plan on later using the allMachines array to create a JSON file, however this infinite loop is halting all potential progress. I've tried to move the connection.on('error', ...) in the SSH function which I think is causing the infinite loop, however this has proved to be fruitless.
Any help would be greatly appreciated - thanks!
P.S If anyone knows how I would be able to register when readlines has finished, and the allMachines array has been filled with the necessary data I would also be very grateful! I've tried to use readline.on('close', ...), however this gets called before SSH and ping finish executing, so is no use to me! Thanks again

Connection closed by application error when iterating through cursor and updating documents

I have following simple node.js app which creates cursor from query which sorts collectoin by City and then temperature. After that, I iterate through cursor and update every document with highest temperatures for every city by adding highest : true.
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
console.dir("Closing database connection");
return db.close();
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
});
}
});
});
The problem here is that only first city gets updated properly, here is the output:
'Berlin is 81; ' 'Successfully updated: 1' 'Paris Florida is 83; '
'Warsaw New Mexico is 57; ' 'Barcelona Vermont is 57; ' 'Closing
database connection' Error: { [MongoError: Connection Closed By
Application] name: 'MongoError' } Error: { [MongoError: Connection
Closed By Application] name: 'MongoError' } Error: { [MongoError:
Connection Closed By Application] name: 'MongoError' }
My guess on what is happening is: the cursor goes through all documents calls update on those with highest temperatures:
db.collection('data').update(query, operator, function(err, updated)
but before the callback returns, cursor finishes iterating and this fragment of code is called which closes connection:
if(doc == null) {
console.dir("Closing database connection");
return db.close();
}
after that, all updates which didn't finish processing will error out since no db connection is available.
What's the proper way of handling it so that connection is closed only after all documents are updated successfully?
As Neil mentioned, we can use .stream(), but I was able to make the program execute as expected by counting already processed updates and closing db connection after all documents which we expect to be updated were updated.
In my case it was pretty simple since I have only 4 cities in database, so I expect only 4 documents to be updated. We could also obtain this number through the query and counting results, but that's good enough for me.
Here's the working code:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
var updatedCount = 0;
var expectedToUpdate = 4; // Hardcoded, but we might want to obtain it pragmatically
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
updatedCount++;
if (updatedCount == expectedToUpdate) {
console.dir("updated expected number of documents. Closing db.");
db.close();
}
});
}
});
});
I usually find the node stream interface to be a better option for an iterator. There is a .stream() method on the cursor object for this:
var stream = db.collection('data').find().sort(
{ City : 1, Temperature : -1 }
).stream();
stream.on('data',function(data) {
// do things with current document
// but pause on things with a callback then resume;
stream.pause();
db.collection('data').update(query, operator, function(err, updated) {
// resume the stream when this callback is done
stream.resume();
})
});
stream.on('end',function() {
// Called when everything is complete
// db.close is safe here as long as you are no longer using the connection
db.close();
});
In fact from version 2.0 of the native driver the stream interface is part of the default cursor object.
But in general, only call db.close() for one off processing scripts. You should generally not be calling it at all in server type implementations and just leaving the connection open over the life-cycle.

Calling a function from within a callback causes node app to hang

I have updated the post with the actual code.
The problem is that the node app hangs and does not exit unless I comment out the query in addArticle. I am wonder what I'm doing wrong here (in regards to the hanging problem).
function addArticle(title, text, date, link) {
connection.query("SELECT * FROM articles WHERE link LIKE "+connection.escape(link), function(error, rows, fields) {
if(rows.length == 0) {
console.log("article not in database");
console.log(connection.escape(title));
var values = [connection.escape(title), connection.escape(text), date, connection.escape(link), '{}'];
connection.query("INSERT INTO articles (title, text, date, link, topics) VALUES ?", [[values]], function(err) {
if(err) throw err;
});
}
});
}
function scrapeReuters() {
var url = 'http://www.reuters.com/news/archive/technologyNews?date=10092013';
request(url, function(err, resp, body){
$ = cheerio.load(body);
links = $('a');
$(links).each(function(i, link){
var addr = $(link).attr('href');
if(addr != undefined && addr.indexOf('article') != -1 && addr.indexOf('http') == -1 ) {
var full_link = "http://www.reuters.com"+addr;
var title = $(link).text();
request(full_link, function(err, resp, body){
$ = cheerio.load(body);
para = $('p').text();
addArticle(title, para,new Date().getTime(), full_link);
});
}
});
});
}
You probably need to close the connection after all the queries have finished. You can try using the https://github.com/caolan/async library to run the queries in sequence and then in a master callback, close the connection.
Its a little tricky, but first you need to define an array of functions to execute. Then you run async.sequence(arrayOfFns,masterCallback). The master callback gets errs and results (notice plural, its from all the functions). In that master callback, terminate the mysql connection/and or end the process.
To do this, I would rewrite the addArticle query to just return the query string. Then before your $(links).each loop, I would make an array called toInsert
In each loop I would say
toInsert.push(function(callback) {
connection.query(addArticle(...),function(err) {
if(err) callback(err);
else callback(null,true);
});
});
Then after the loop run
async.sequence(toInsert,function(errs,results) {
connection.close() //not sure if correct
process.exit(); //maybe, if needed?
});

Categories

Resources