Calling object functions in middleware - javascript

I have this code in my middleware:
const UserMiddleware = {
isNumber(n) { return !Number.isNaN(parseFloat(n)) && !Number.isNaN(n - 0); },
// eslint-disable-next-line consistent-return
validateSignUp(req, res, next) {
const allSignUpErrors = [];
console.log(this.isNumber(5));
if (this.isNumber(req.body.first_name)) {
allSignUpErrors.push('First name must be a text value');
}
if (allSignUpErrors.length !== 0) {
return res.status(400).json({
status: 400,
error: allSignUpErrors,
});
}
next();
},
I normally use 'this.' to call functions and variables in objects without problems. I suspect that the 'next()' function in the middleware is what is causing me to get the error below at the point of using 'this.' to call a function.
TypeError: Cannot read property 'isNumber' of undefined
I have tried using 'bind' to call the function but the 'undefined' error still occurs.
Is the 'next()' function the one breaking the normal functionality? Is there a way to correctly use 'this.' to call functions in middleware?

Change:
this.isNumber(...)
to:
UserMiddleware.isNumber(...)
The value of this inside a middleware function will not be your UserMiddleware object unless you specifically used .bind() or some similar technology when passing it as middleware.
For help with further options, show us the code where you're using validateSignUp().
For example, if you were doing:
app.use(UserMiddleware.validateSignUp);
Then, you could set the desired value for this by using .bind() like this:
app.use(UserMiddleware.validateSignUp.bind(userMiddleware));
Passing UserMiddleware.validateSignUp to a function immediately loses the association with the UserMiddleware object and the this value when that function gets called will be determined by how the caller calls the function and won't be the UserMiddleware object. Using .bind(UserMiddleware) forces the desired this value to be set. .bind() actually creates a wrapper function who's sole job is to reattach the desired this value and that wrapper function is what is passed as the middleware handler. The middleware infrastructure calls the wrapper function with the wrong this value and then the wrapper function calls your validateSignUp function with the desired value of this - probably using .apply().
For a look at how .bind() works, you can see a polyfill for it here on MDN. For more of a discussion of how the value of this is set, see Six ways of setting this.

Related

How to specify a parameter that can be undefined in flowjs

I'm new to flowjs and do not yet understand how the typical use case of an undefined parameter should be modeled in flowjs.
function msg(message: string, callback: ?Function) {
// ...
if (_.isFunction(callback)) {
callback();
}
}
When checking the above function with flow, the following error message is shown:
Function cannot be called on possibly null value function call.
Function cannot be called on possibly undefined value
I do understand why the errors are shown but I'm not sure how to tell flowjs that this is intentional because the callback is only invoked when the parameter is not null or undefined?
Flow does not know that _.isFunction(callback) returns true only if callback is a function. All it knows is that it returns a boolean (if you have the interface file for underscore/lodash set up). You should do native JS checks instead, then Flow can refine the type of callback from ?Function to Function. Like this: if (typeof callback === 'function') { callback() }.
A simpler type check should work as well: if (callback) { callback() } because Flow knows that if callback is not falsey, it has to be a function.
See more at https://flowtype.org/docs/dynamic-type-tests.html

How to receive default arguments in a javascript function like node or express HTTP functions?

In express.js when we call
app.get(function(req,res){...}),
the function automatically receives request and response objects and we can give any name to function parameters like req,res or re,rs and many others.
I want to create a function that will rest in an object.
When I want to use this function it must receive default arguments which may be e.g simple int 4,3 and I must be able to specify parameter names as per my choice.And these arguments must be assigned to parameter names I have defined and I must be able to use those name in code inside function.
How can I achieve this?
You can write your own middleware for this. For example this is how I control the mandatory fields in requests :
router.post('/relations', controlBodyMiddleware(['userIdReceiver']), relation.create);
While you can have method like this :
controlQueryMiddleware(fields) {
return function(req, res, next){
if (!req.body.mandatoryField || req.body.mandatoryField !== 5){
return next(new Error('I want mandatoryField equal to 5'));
}
req.body.myFieldAccessibleInNextMiddleware = 'Yes, this would be there';
next();
};
}
I have found the solution myself.
It was all related to call back functions and passing the function definition to another function.
var app={
get:function(callback){
callback('Request object..','Response object..');
}
};
app.get(function(rq,rs){
console.log(rq,rs);
});
Here we can pass function definition in get method with parameters of your own choice that's what I wanted to know.
It is not necessarily express object or methods.
app can be any object and get can be any method of app.
With of course parameters not necessarily req and res objects.

Node.js - strange TypeError when function being called twice within class

Consider this (simplified) extract from a class:
function PluginsEngine() {
this.allPluggins = require('./plugins');
};
PluginsEngine.prototype.applyPlugins = function(incomingData, done){
// bind the incoming data to each plugin
var key;
for (key in this.allPluggins)
this.allPluggins[key] = this.allPluggins[key].bind(undefined, incomingData);
async.parallel(this.allPluggins, done);
};
The constructor loads a set of anonymous functions and the "applyPlugins" method then passes the "incomingData" (string) to each and these are executed using async.
When writing tests against this I am seeing a strange behavior in that calling "applyPlugins" runs fine, but calling it again immediately afterwards causes the error:
TypeError: string is not a function
Adding some additional debug, I can see that allPluggins is empty (functions not available) when run the second time.
Can anyone advise why the variable is losing the functions?

javascript requestAnimationFrame in class [duplicate]

The function to render my canvas is a prototyped method of a class, like this:
Engine.prototype.renderCameras = function() {
console.log('render ok');
}
When I try to run this code directly, it works fine:
engine.renderCameras()
>>> render ok
When I try to run it using requestAnimationFrame, in either Chrome or Firefox, I get this:
window.requestAnimFrame(engine.renderCameras())
>>> render ok
>>> Error: Component returned failure code: 0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS) [nsIDOMWindow.mozRequestAnimationFrame]
It runs, but it always throws an error. That's not cool.
When I try to run it like this:
window.requestAnimFrame(engine.renderCameras)
>>> 0
It just does nothing.
I was able to solve this problem by using a closure, but I'd still like to know why I can't pass a function like that to requestAnimationFrame.
window.requestAnimFrame(engine.renderCameras())
is not passing a function to requestAnimFrame, it is passing the return value of engine.renderCameras to requestAnimFrame. The return value is probably not a function and that's why you get this error.
window.requestAnimFrame(engine.renderCameras)
instead correctly passes a function reference, but then this [docs] inside renderCameras won't refer to engine. If you rely on that (which I assume based on the setup), you either have to pass a function calling engine.renderCameras properly:
window.requestAnimFrame(function(){
engine.renderCameras();
});
or use .bind [docs] to set (and bind) this explicitly:
window.requestAnimFrame(engine.renderCameras.bind(engine));
Either way, you have to repeatedly call window.requestAnimFrame to get the next animation frame, which means you typically use a recursive function. For example:
window.requestAnimFrame(function render(){
engine.renderCameras();
window.requestAnimFrame(render);
});

Issue with variable scope in NodeJS, Express, Prototyping

File: MainApp.js
var reqHandler = reqire('HTTPRequestPostHandler')..
...
...
var httpRequestHandler = new reqHandler();
app.post('/', httpRequestHandler.handleRootPost);
File: HTTPRequestPostHandler.js
HTTPRequestPostHandler =function(){
this.someVar = value;
}
HTTPRequestPostHandler.prototype.handleRootPost{
console.log(this.someVar) //Error -> this.someVar is undefined.
}
I have these 2 files. The MainApp.js is where express is configured and various handlers for each endpoints e.g. '/'.
But when a post request occurs and the request handler (HTTPRequestPostHandler.prototype.handleRootPost) is invoked, I get a undefined error while accessing the variable this.someVar.
Why is this happening. What am I doing wrong here.
It's not a scope issue, it's a this issue.
Normally in JavaScript, this is set entirely by how a function is called, not where it's defined. So what's happening is you're passing your method in as a callback, but since it's not being called in a way that sets this to be your instance. (The next version of the specification, ES6, will have "arrow functions" that have this bound to them rather than being set by how they're called.)
The usual way that this gets set during a function call is when you call the function as part of an expression retrieving the function reference from an object, e.g.
foo.bar();
That calls bar with this set to foo. But this:
var f = foo.bar;
f();
...does not. this will be undefined (in strict mode) or the global object (in loose mode).
Other ways to set this are via Function#call and Function#apply, which let you call the function and explicitly say what this should be.
You can solve this with bind:
app.post('/', httpRequestHandler.handleRootPost.bind(httpRequestHandler));
bind returns a function that, when called, will call the original function with this set to what you pass in as the first argument.
More (on my blog):
Mythical methods
You must remember this

Categories