What doesn't nodejs relate 'this' as the object that encapsulates the function? - node.js

I wrote the following code in nodejs:
var express = require('express');
var app = express();
app.message = "helloworld";
app.get('/check', function (req,res) {
res.end("GET request OK");
console.log(this.message);
});
app.listen(4000);
When I run the code and send a GET request, the line:
console.log(this.message);
prints "undefined".
However, when I change it to:
console.log(app.message)
I get "helloworld".
I thought that this variable should represent the object that invoked the function. If so, why doesn't this object include the attribute .message ?

this can be whatever the author of the library intends it to be. It could be the app instance or it could be the global object.
In this case, it appears it's the global object.
As a sidenote too, it's not recommended to add expando properties to an existing library like that.

Related

Please explain the basic server setup code of Express.js

In this code snippet:
Const express = require('express')
Const app = express();
/*Typeof express = function
Typeof app = function*/
app.get()
My question is: if app is a function then how can we use a dot operator with it to call get function, and if we are creating a object of function express then why didn't we use new keyword to create an object.
Secondly, module.exports exports the literals in object format then why we are getting typeof express here a function.
If I am wrong anywhere, please correct me.
In JavaScript functions are objects, so this is valid:
function x() {
console.log("this is x()");
}
x.y = function() {
console.log("this is x.y()");
}
x();
x.y();
Express and other JavaScript tools use this feature extensively.
If you're used to other languages where functions are just functions and not objects themselves this will seem extraordinarily strange.

How to check the content of Koa's ctx.query?

For a Koa-based API server, I want to check what parameters the URL query contains.
My setup looks as simple as this:
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
router = new Router()
router.get('/', ctx => {
console.log(ctx.query)
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)
It seems that ctx.query has a structure like an object but doesn't work as one.
Methods like ctx.query.hasOwnProperty() or ctx.query.toString() result in an error saying that it is not a function.
Though, Object.keys(ctx.query) gives an array of the keys—which is confusing to me because it apparently is an object and should have above methods.
What is ctx.query exactly? How can I make the failing methods from above working?
ctx.query is the return from Node.js' querystring.parse() method. From the documentation:
The object returned by the querystring.parse() method does not
prototypically inherit from the JavaScript Object. This means that
typical Object methods such as obj.toString(), obj.hasOwnProperty(),
and others are not defined and will not work.
You can check Koa's request implementation.

Restify set method like in Express

In Express 4.0, after declaring the server I do the following to set a server-wide variable...
var app = express();
app.set('foo', 'bar');
I don't see a method like that in Restify's documentation, so I'm just declaring an object inside the server that holds my variables.
Is that correct? Is there a better way to do this in Restify?
It sounds like that would work, but why not just create a module to hold your variables? Create a file named vars.js somewhere appropriate and make it like this:
module.exports = {
my_var: 2112,
other_var: 'signals'
}
Then wherever you need access to those variable just
var all_vars = require('./path/to/var.js');
and you'll have them.

Global variable across all controllers in Node JS

I am trying to have a variable which can be accessible by all controllers in my node project. Currently in one controller I have:
var ua = req.headers['user-agent'];
var isMobile = "no";
if(/mobile/i.test(ua))
isMobile="yes";
It's pointless to copy past all of this for all my controllers and pass the isMobile variable to the view. I'd like to get the value of isMobile set once, and then pass it wherever I want from my controllers.
Is there an easy way to do this rather than have those 4 lines of code copy pasted in every controller?
Thanks
You'll want to use a Sails policy for this:
// /api/policies/isMobile.js
module.exports = function(req, res, next) {
var ua = req.headers['user-agent'];
req.isMobile = /mobile/i.test(ua);
next();
}
// /config/policies.js
module.exports.policies = {
'*': 'isMobile'
};
This will run the code before every controller action, and give you access to the req.isMobile var in all of your custom controller code.
A truly global variable isn't particularly an option as any concurrency above 1 will likely result in unexpected behavior. Being that it is something particular to the unique request itself, the req object is likely your best bet.
Assuming you have access to the req object everywhere that you would like to utilize use this flag, you can simply add a property to the req object at any point (preferably early in the request/response cycle). After this property is added, it should be available everywhere that has access to req.
req.isMobile = /mobile/i.test(req.headers['user-agent']) ? 'yes' : 'no';
Or if there is a concept like middleware in express for sails
function isMobile(req, res, next) {
req.isMobile = /mobile/i.test(req.headers['user-agent']) ? 'yes' : 'no';
next();
}

In Express.js, how can I render a Jade partial-view without a "response" object?

Using Express.js, I'd like to render a partial-view from a Jade template to a variable.
Usually, you render a partial-view directly to the response object:
response.partial('templatePath', {a:1, b:2, c:3})
However, since I'm inside a Socket.io server event, I don't have the "response" object.
Is there an elegant way to render a Jade partial-view to a variable without using the response object?
Here's the straight solution to this problem for express 3 users (which should be widely spread now):
res.partial() has been removed but you can always use app.render() using the callback function, if the response object is not part of the current context like in Liors case:
app.render('templatePath', {
a: 1,
b: 2,
c: 3
},function(err,html) {
console.log('html',html);
// your handling of the rendered html output goes here
});
Since app.render() is a function of the express app object it's naturally aware of the configured template engine and other settings. It behaves the same way as the specific res.render() on app.get() or other express request events.
See also:
http://expressjs.com/api.html#app.render for app.render()
https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x for express 2.x > 3.x migration purposes
You can manually compile the Jade template.
var jade = require('jade');
var template = require('fs').readFileSync(pathToTemplate, 'utf8');
var jadeFn = jade.compile(template, { filename: pathToTemplate, pretty: true });
var renderedTemplate = jadeFn({data: 1, hello: 'world'});

Resources