I'm using the async waterfall method in my application and I need to specify the arguments in every callback function.
async.waterfall([
function (next) {
Client.remove({ store: store }, next);
},
function (objectsRemoved, next) {
Item.remove({ store: store }, next);
},
function (objectsRemoved, next) {
Store.remove({ _id: store.id }, next);
},
// ...
The code above works fine in the server, but fails in my local environment. This is because the callback arguments for mongoose's Model.remove differ on both sides.
In the server I get function (err, objectsRemoved)
Locally I get function (err, objectsRemoved, anotherObject)
The weird thing is that in both cases I'm running the same version of mongodb (2.4.9) and mongoose (3.8.20).
Any idea of what could be happening?
Related
I have configured a middleware (router level) which checks for admin access, and if successful I am logging the information and calling next().
middleware:
const validateAdmin = function (scope) {
return function (req, res, next) {
if (req.admin) {
//log the information and using scope to log
next();
} else {
// send the response with 403
}
};
};
router level usage
router.use('/rule/:name', validateAdmin({ serviceScope: this.#serviceScope }), async (req, res) => {
await this._handleRequest(req, res);
});
working case
when i trigger the req from postman, i can see that middleware is called and after next getting executed, the control is coming to 'await this._handleRequest(req, res);' which is expected.
issue
Test case
it.only('shall get single rule', async function () {
const getSingleReq = {
method: 'GET',
admin: true,
originalUrl: '<some req>/rule/rule_1',
baseUrl: '<some_req>',
query: {},
params: { name: 'rule_1' },
headers: {
//token info
},
body: {}
};
const next = sinon.spy();
await router.use.args[1][1](getSingleReq, res, next);
}));
when await router.use.args[1][1](getSingleReq, res, next); is called, I can see the middleware is triggered but next() is not calling the subsequent middleware. I expect that await this._handleRequest(req, res); is called just like the scenario when triggered from postman.
I hope the issue is clear.
Referred many use cases but everywhere the scenario of just checking if next() is called is only done .
https://github.com/jfromaniello/express-unless
Two questions..
Any idea why this does not work?
It appears this library is abandoned. Are there any other alternatives?
handleExpiredTokens.unless({
path: [{
url: '/foo',
methods: ['POST']
}]
});
function handleExpiredTokens(err, req, res, next) {
// stuff
}
handleExpiredTokens.unless = unless;
module.exports = handleExpiredTokens;
handleExpiredTokens runs on every request including POST /foo
getting a protectWithCSRF.unless is not a function
So basically I am trying to carry out function synchronously using next but Its not happening synchronously: Route.JS
router.post('/era',function(req,res,next){
console.log("got request");
controlleri.book(req,res,next);
booking_controller.book(req,res);
console.log("done in server.js");
next();
});
controlleri.book and booking_controller.book both have database calls but
Inspite of adding next() in controlleri.book, booking_controller.book starts executing before next being called in the first function.
Tell me if both functions are needed.
Edit:
Tried using async library still its not going synchrounosly Code:
router.post('/era',function(req,res){
console.log("got request");
async.series([
function(callback){
console.log("hi");
controlleri.book(req,res);
callback(null);
},
function(callback){
console.log("hias");
booking_controller.book(req,res);
callback(null);
}
]);
Second function begins before completing First one
Both of your functions take req, res and next as their arguments which is a signature for a middleware function. Further, express middleware is executed in order. Why not just make each of your functions into their own middleware and in the execution order you need them in?
// POST executes controlleri.book
// then booking_controller.book,
// then the log code
router.post('/era', controlleri.book, booking_controller.book, function(req, res, next) {
console.log("done in server.js");
});
This way, next within controlleri.book will be booking_controller.book, and next in booking_controller.book will be the last method that logs "done in server.js"
Use aync library for doinf operations syncronously.
next() is a middleware which tells that the request shouldn't be returned but there are more functions to be applied on the request.The functions it gets to operate are performed asynchronously because that's node's default behaviour.
async.series([
controlleri.book(callback){
// do some stuff ...
callback(null, 'one');
},
booking_controller.book(callback){
// do some more stuff ...
callback(null, 'two');
}
],
// optional callback
function(err, results){
// results is now equal to ['one', 'two']
});
async.series takes an array of functions to be performed in order (synchronously). The callback passed in each function is mandatory.
Please, tell me what I am doing wrong:
My backbone view creates and saves document in mongodb by mongoose and uses the data in the view allright upon the backbone save() and fetch() methods. But when i use Backbone model.save({option: 'modified'}); with route.put() on the backend, jquery fires ERR_CONNECTION_RESET. I tried lots of things i found in the net, but they did not work. Maybe i need to use ajax.Prefilter or something of this kind, but i do not know exactly what to do.
the piece of code in backbone view firing update is:
this.user.save({ options: 'modified' }, {
wait: true,
success: function(model, response) {
console.log('saved');
},
error: function(model, error) {
console.log(error);
}
});
in router index.js
router.put('/user/:id', require('./user').put);
it works because on GET route it works perfectly well.
in user.js
exports.put = function(req, res) {
var query = { _id: req.params.id };
User.update(query, { options: req.body.options }, function(){
res.send('ok');
});
};
I also experimented a lot with id or _id, and various ways of using mongoose update, like
User.findOne({ _id: req.params.id }, function (err, doc){
if (err) return console.log(err);
doc.options = req.body.options;
doc.save(function(err){
res.json(doc);
});
});
and others such like. It did not work. Here is the error (it must be the key to my problem, but i cannot figer it out)
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience.
PUT http://localhost:3000/user/56349be42b19125405c2d66a
net::ERR_CONNECTION_RESET
It was silly: maximum req size exceeded. Cured by setting
app.use(bodyParser.json({limit: '16mb'}));
app.use(bodyParser.urlencoded({ limit: '16mb', extended: true }));
Background
Yes, there are a lot of different Node.js logging library winston, bunyan and console.log. It's easy to log down the information of the specific request when it has called and when and what information would be in response.
The problem
The problem begins with the sub function calls. When under one request your calling multiple functions which also uses the same logging, how would you pass the request meta - data to these log calls (function parameters seems to be one possible way but these are really messy) ?
Example
Small visual for coders:
// Middleware to set some request based information
app.use(function (req, res, next) {
req.rid = 'Random generated request id for tracking sub queries';
});
app.get('/', function (req, rest) {
async.series({
'users': async.apply(db.users.find),
'posts': async.apply(db.posts.find),
}, function (err, dbRes) {
console.log('API call made ', req.rid)
res.end(dbRes);
});
});
// Now the database functions are in other file but we also need to track down the request id in there
(db.js)
module.exports = {
users: {
find: function () {
console.log('Calling users listing ', req.rid); // ERROR this is not possible to access, not in this scope
// Make query and return result
}
},
posts: {
find: function () {
console.log('Calling post listing ', req.rid); // ERROR this is not possible to access, not in this scope
// Make query and return result
}
}
};
You can log your requests with simple conf in your app.js with;
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
});
However, you need to provide logs for specific functions in your controller.