node.js express.js Error handling in View - node.js

I am very new to node.js and express.js and in programming concepts. I already made a basic MVC modeled app on node and express.
My problem is how do you handle error, I got this following code:
exports.submitBloodRequest=function(kaiseki,resView,request){
var params = {
bloodCenterId:request.session.centerID,
bloodTypeId: request.body.bloodType,
requestQuantity:request.body.numberOfDonors
}
kaiseki.createObject('blood_center_request', params, function(err, res, body, success) {
if(success){
resView.redirect('/bloodRequest')
}else{
//WHAT TO DO HERE?
}
});
}
Kaiseki is just a middleware for parse.com, I don't know what to do if it got error. Usually I use ajaxForm.js to look for BadRequest then use javascript to display error message in my view.
I want my error to appear in the same page, where it is success, should I pass a json error to my view?
Or still use ajaxForm.js and instead of res.render or res.redirect I should use res.status(500)
Is there anyway to handle the error and showing it into the view. Without using any javascript to detect BadRequest?
And can a view have a optional variable? In my view If I didnt pass any value on it it gives me error like if i have #{variable} it asks for its value. Can it be made to be optional? Im using Jade Template

To respond to an XHR request with an error you can do something like return resView.status(500).send(err); which will send the err object back as JSON. If you want to render an HTML error page instead you can do return resView.status(500).locals({err: err}).render('/errorPage');
You didn't say which template engine you are using but most likely the #{} version will automatically escape HTML characters for you (turn < into <, etc) to avoid XSS attacks and rendering problems whereas !{} will render the contents of the variable directly without escaping, which is dangerous if the variable contains any user-generated content, but necessary if the variable has HTML you want rendered by the browser.

Related

Body is not getting parsed in GET method

I am using mockoon for API simulation. I created 2 routes there with method GET and its body contains(responds with) JSON object. I noticed that my express app is not able to parse one of the routes. But the route that has JSON object in body which contains ARRAY is getting parsed. I tested both routes with Express(by console.log) and in chrome browser(I have JSON formatter extension) and it is behaving the same meaning response that does not contain ARRAY is not getting parsed but the response with array is getting parsed(behaving normally). Let me show the screenshots:
Express(by console.log):
With array:
Without array:
Chrome(JSON Formatter extension):
With array(extension is able to parse):
Without array(extension is not able to parse):
I tried adding Header(Content-Type: application/json) to the route in mockoon. But still, I am not aware of what is going on here. Someone please explain
The express code:
const iabs_client = await axios.get(
"http://localhost:3001/iabs-client
);
Here is the route created in Mockoon(without array inside JSON):
P.S mockoon is a program that creates endpoints in localhost, useful for API simulation when developing front-end without having backend yet
The trailing comma after "something" is not valid JSON. Edit your Mockoon body to remove the comma and it should work.

how to log js errors at server

I wanted to know does YUI3 provides any way to try and catch errors functionality, where in after the error is captured we can show some customized error alert and simultaneously log the error at server side with the error exceptions and other details.
Also if this functionality is not there in yui3 then which all frameworks do one need to use to do this and which all are compatible with YUI.
I'm not aware of YUI3 providing exactly what you're after out-of-the box.
You can split your question into two parts:
Capturing errors
You either wrap your code with try/catch blocks or use a global error handler. It looks like YUI3 doesn't yet directly handle this (http://yuilibrary.com/projects/yui3/ticket/2528067) but handling it shouldn't be too hard, you'll just have to test for browser differences.
Sending Error data to the server
You ought to be able to use Y.IO to send back the error data to the server. It looks like you get errorMsg, url, lineNumber given to you, so you can just send them back to the server:
YUI().use("io-base",function(Y){
window.onerror = function(errorMsg, url, lineNumber){
Y.io("/errorHandler.php", {
data: {
errorMsg: errorMsg,
url: url,
lineNumber: lineNumber
}
});
alert("Sorry, something bad happened");
};
console.log("handler registered");
//now trigger an error
a.b.c="banana";
});
That seems to work here: http://jsfiddle.net/J83LW/
I'l leave the customized alert to you, I've left an alert here as a basic example of handling this

Accessing jQuery object in JADE

During login, I save the userId in a jQuery cookie, so that I can access it by $.cookie('userId').
Now that I am trying to access it from Jade, as,
- if ($.cookie('userId') === userId)
I get an error
$ is not defined
How can I access the cookie ?
My code:
- if (($.cookie('userId')) === userId)
input(type='submit', value='Move')
else
input(type='submit', disabled, value='Move'')
You seem to misunderstand concepts. Let me give you a lecture. ;)
Basics. Cookie is stored on the client-side. So using jQuery $.cookie('userId') will retrieve it when this script is run on the client-side.
But here you use JADE templating engine on server-side. So you didn't even send the page to the client-side yet. So what cookie do you want to retrieve? There is no cookie, because you are at the server.
There's more. Running $.cookie('userId') throws the error, because you are on the server-side. There is no $ object. And there cannot be, because you cannot use jQuery on server-side (well, actually you can, but this is irrelevant at the moment). Did you define $ object in your route system? Or did you define helper $? I don't think so.
Express+JADE tutorial. Now let me give you a short tutorial. Say you have a view (in app.js)
app.get('/', function(req, res){
res.render('index.jade', { code: 500 });
});
Now in index.jade you can use code as a variable. So you can write your index.jade for example like this:
// some code
- if (code == 500)
input(type='submit', disabledm, value='Move')
- else
input(type='submit', value='Move')
// some code
and now it will work! You may also use JavaScript functions in template if you predefine them. For example (in your app.js)
app.helpers({
positive: function(no) { return no > 0; }
});
then in index.jade template you can use
- if (positive(-13))
input(type="submit")
and even combine these two concepts
- if (positive(code))
// do some stuff
To cookie or not to cookie. If you really need to use cookies (and you shouldn't except for sessions or CSRF for example) then you need to use client-side JavaScript. This means that you need to add (after jQuery)
script(src='my-path/my-script.js')
to the index.jade file and write my-script.js like this
$(document).ready(function() {
if ($.cookie('userId') == userId) {
// do something like append input to some holder
}
});
But there are several problems with that solution. First: what is userId (second part of equality)? You need to predefine it in your index.jade. For example using
script
var userId = #{ user.id };
and adding user object in your route. Second: cookies are local variables. Setting them requires additional server code which I do not thing you would like. This makes maintaining the app harder. And finally: storing a user's id in a cookie seems to be pointless. The final user don't even have to know it's own id. The server needs to know! Sessions system comes handy here.
Final note. The code you wrote shows us that you cannot distinguish between server-side and client-side JavaScript. The solution to your problem is to learn, learn and learn. Read tutorials and everything about JADE, Express and Node.js.
What #freakish said is right. You're trying server side vs. client side.
If the cookie is set you should be able to access it on server like so
app.use(express.cookieParser());
app.get('/', function(req, res){
// index is jade template
// local variable on jade template holds cookie value
// use req.cookies.userid
res.render('index', { userid: req.cookies.userid });
});

Jade template, how to pass concrete object to pages?

I have a jade template for my node.js project. I would like to send an object to the jade template and pass it to a function inside the page (to render something).
I am sure I send the right stuff from the server like this
res.render(__dirname + '/pages/viz.jade', {
vizJson: newJson,
});
in the client I do something like this:
script
sunburst(#{vizJson})
Thus, inside a script function, I want to call a function that creates my visualization with some json I created on the server side.
The problem is that when rendered I have something like sunburst([Object object]). I also tried to send the stringified version of the JSON but when I do JSON.parse(#{vizJson}) it complains like Unexpected token &.
The json I send is always different and has different level of depths.
Does anyone knows what to do?
Thanks
I hope this is going to help someone. I solved it like this:
script
sunburst(!{JSON.stringify(vizJson)})
Notice the ! and the {...} wrapping the stringify method.
For this to work, you need to stringify on the server.
res.render(__dirname + '/pages/viz.jade', {
vizJson: JSON.stringify(newJson),
});
Then, as you mentioned, parse the JSON on the client.
script
sunburst(JSON.parse(#{vizJson}))
Hope that helps!
Oddly enough, for me the solution involved no calls to JSON.parse. I stringified my object on the server and just used the !{vizJson} method and got my object clientside.
Per the docs, unescaped string interpolation: http://jade-lang.com/reference/interpolation/
On the JS side, you send back
res.render(__dirname + '/pages/viz.jade', {
vizJson: JSON.stringify(newJson),
});
On the HTML side, I have found that something like:
JSON.parse( '!{vizJson}' )
works.

Render template to variable in expressjs

Is there a way to render template to a variable instead to output?
res.render('list.ejs', {
posts: posts
});
something like this
var list = render('list.ejs', {
posts: posts
});
The easiest way to do that is to pass a callback to res.render, in your example:
res.render('list.ejs', {posts: posts}, function(err, list){
//
});
But if you want to render partial templates in order to include them in another template you definitely should have a look at view partials.
I am quite a newbie on express.js, anyway I am not sure you can access the rendered string that way, although if you look at express' "view.js" source on github (here) you see that it's accepting a callback as second argument, if that may help: you may access the rendered string there.
Otherwise, I think it's quite easy to patch the code to add a method returning the rendered string without sending it: on line #399 you have the very call that gives the string you are looking for.
This wasn't the question originally asked, but based on comments from the OP and others, it seems like the goal is to render a partial via json (jsonp), which is something I just had to do.
It's pretty easy:
app.get('/header', function (req, res)
{
res.render('partials/header', { session: req.session, layout: null }, function (err, output)
{
res.jsonp({ html: output });
});
});
Note: In my case, the header partial required the session, and my template library (express-hbs) needed layout: null to render the partial without using the default layout.
You can then call this from Javascript code in the client like any other JSONP endpoint.

Resources