Pass arguments to nested function - javascript

I have some code duplication that I'd like to factorize.
app.post('/login', (req, res) =>{
reqOptions = {...};
request(reqOptions, (error, response, body) => {
if (!error) {
res.statusCode = response.statusCode;
res.json(body)
}
else {
res.statusCode = 503;
res.json(body)
}
});
});
The logic in the request callback is always the same, and I try to find a way to get it out into a reusable function, like this :
function requestCallback(error, reponse, body) {
....
}
app.post('/login', (req, res) =>{
reqOptions = {...};
request(reqOptions, requestCallback);
});
My problem is : how can I get access to req and res in the requestCallback() function ? Do I need to pass everything as arguments ?
Many thx

You can use Function.prototype.bind()
function requestCallback(_req, _res, error, reponse, body) {
....
}
request(reqOptions, requestCallback.bind(null, req, res));

Yes, you can just simply pass req and res as arguments to requestCallback()

Related

Pass Parameter to Function Express JS

everything good ? I would like to know the best way and if it is possible to send a certain parameter to an express function in the NodeJS.
i wanna pass the string ('admin') or other string that i want to function 'RoleTolen', using my route.
function verifyToken
function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers["authorization"];
// Check if bearer is undefined
if (typeof bearerHeader !== "undefined") {
// Split at the space
const bearer = bearerHeader.split(" ");
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
} else {
// Forbidden
res.sendStatus(403);
}
}
function ValidToken
function validToken(req, res, next) {
jwt.verify(req.token, process.env.SECRET, (err, authData) => {
if (err) {
res.sendStatus(403);
} else {
next();
}
});
}
function RolesToken
function rolesToken(role, req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
}
my route
router.post(
"/posts",
verifyToken,
validToken,
rolesToken("admin"),
customerController.posts
);
function rolesToken(role, req, res, next) is not a proper Express.js route handler, as you already know (and hence the question, I assume).
What you can do is to write your rolesToken as a function that returns the actual Express.js compliant handler (function):
function rolesToken(role) {
return function(req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
};
}
from the docs
Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature (err, req, res, next)):
Therefore your RolesTaken function won't work as expected.
Secondly, you can create a middleware or modify existing one
(req, res, next) => {
//some stuff
if(req.path == '/posts') req.role= 'admin';
if(req.path == '/someOtherPath') req.role= 'someRole';
//some other stuff
}
Now you can get the get the role in req.someProp in the your controller middlerware as req.role
you would like to see this question also

Pass values from referenced function in promise-chain?

I'm writing some rendering-code for an Express app, I wish to catch errors and then output them in the function render, but I'm not sure how I'm going to move them from one method to the other.
app.get('/user/makeRider', auth,
(req, res, next) => {
req.user.user.makeRider(req.query)
.catch(error)
.then(render(req, res));
}
);
var render = (req, res) => {
var response = {
params: req.query,
user: req.user.fulluser
};
res.json(response);
},
error = (reason) => {
reason.errors.forEach((error) =>{
console.log(error);
});
return;
};
You can use error function as your last midleware in the chain and simply pass the request to the next chain:
var render = (req, res) => {
var response = {
params: req.query,
user: req.user.fulluser
};
res.json(response);
}
app.get('/user/makeRider', auth,
(req, res, next) => {
req.user.user.makeRider(req.query)
.catch(next)
.then(render(req, res));
}
);
app.use((reason, req, res, next) => {
res.send(reason.errors);
// or you can send them as json: res.status(404).json({errors: reason.errors})
});
Beware of hoisting issue in your code, the variable declarations are hoisted to the top, but not their assignments, error and render function may appear as undefined when accessed from your route.
A quick, but maybe not the most elegant solution would be to add errors as a parameter to your render function, then you could do something like this:
app.get('/user/makeRider', auth,
(req, res, next) => {
req.user.user.makeRider(req.query)
.catch((reason)=>{
render(req, res, reason.errors)
})
.then(render(req, res));
}
);
var render = (req, res, errs) => {
var response = {
params: req.query,
user: req.user.fulluser
};
res.json(response);
};

Remove a field of my json in a specific case

I have an ExpressJS controller that list all my users
userCtrl.get :
get(req, res, next) {
var func = function(err, data) {
if (err) return next(err);
return res.json(data);
};
if (req.params[this.idName])
this._getById(req.params[this.idName], func);
else
this._getAll(func);
}
_getById(id, fn) {
this.ObjectClass.findById(id, fn);
}
_getAll(fn) {
this.ObjectClass.findAll(fn);
}
I'd like to call it from another road, in such a way that res.json() will filter a field of this json
Something like :
router.get ('/services/:serviceKey/authBridge/users', function(req, res, next) {
function anonJs(x) {
x.forEach(s => s.credential = null);
res.json(x);
}
res.json = anonJs;
userCtrl.get(req, res, next);
});
The problem is, with this last piece of code I end up with a recursion as I call res.json that is now defined as anonJS
You must store the reference to the old function before replacing it.
router.get ('/services/:serviceKey/authBridge/users', function(req, res, next) {
var json = res.json;
res.json = function(x) {
x.forEach(s => s.credential = null);
json(x);
}
userCtrl.get(req, res, next);
});

How to call another service (function) before executing the res.view() function call using sails JS

I would like to call a separate function (e.g. a Service function) before sails render the page into html. Please kindly refer my controller code below...
var MYController = {
index: function(req, res, next) {
req.flash("error", "Testing hello world");
MyCustomServices.myFunction( req, res );
res.view();
}
}
Just to add my service function, api/services/MyCustomServices.js
exports.myFunction = function( req, res ){
Test.findOne({ code : "CODE" }, function(err, resp) {
if ( resp ) {
res.locals.TEST = resp;
}
});
var msg = req.flash('error');
res.locals.ERROR = msg.length>0 ? msg : "" ;
};
In this scenario, before executing the res.view there is another process to run when I called MyCustomServices.myFunction( req, res );
The problem is, everytime I have the res.view() function call, I need to add this line in all my controller's action.
I tried to add this MyCustomServices.myFunction( req, res ); in express.js, but it doesn't seem to work as expected. But I think, it should be in express, it is just I don't know what codes I need to add.
What is inside my MyCustomServices.myFunction( req, res ) are:
A query to sails to fetch some data from MongoDB
Parse the req.flash messages to be passed in the views for displaying.
Anyone got idea on this?
If you need to call res.view after your Service has finished executing, you could remove res.view from the controller, and put it in the service itself:
var MYController = {
index: function(req, res, next) {
req.flash("error", "Testing hello world");
MyCustomServices.myFunction( req, res );
//res.view();
}
}
exports.myFunction = function( req, res ){
Test.findOne({ code : "CODE" }, function(err, resp) {
if ( resp ) {
res.locals.TEST = resp;
res.view(); //TADA
}else {
/* Handle Error */
}
});
var msg = req.flash('error');
res.locals.ERROR = msg.length>0 ? msg : "" ;
};
Two Options
Add a callback to your service
var MYController = {
index: function(req, res, next) {
req.flash("error", "Testing hello world");
MyCustomServices.myFunction( req, res, function(){
return res.view();
} );
}
}
exports.myFunction = function( req, res, cb ){
Test.findOne({ code : "CODE" }, function(err, resp) {
if ( resp ) {
res.locals.TEST = resp;
return cb()
}
});
};
-- or (based on your comments) --
You could add a custom response handler to your app. Check out http://sailsjs.org/#/documentation/concepts/Custom-Responses
You can replace res.view() with res.ok() and then modify api/responses/ok.js with your service.
Or you can create your own response if you don't want to mess with ok.js

Express.js request params undefined

I've got the following node/express code:
app.get("/notes/:categoryName", function (res, req) {
var categoryName = req.params.categoryName;
res.render("notes", {title: categoryName});
});
But when I look at req.params, it's undefined.
Yet, in another controller it works fine:
app.get("/api/notes/:categoryName", function (req, res) {
var categoryName = req.params.categoryName;
data.getNotes(categoryName, function (err, notes) {
if (err) {
res.send(400, err);
} else {
res.set("Content-Type", "application/json");
res.send(notes.notes);
}
});
});
What's the deal?
app.get("/notes/:categoryName", function (res, req) {
More attention :
app.get("/notes/:categoryName", function (req, res) {
You switched the params (res, req)

Categories