Cant understand this Express JS source snippet - javascript

I was trying to understand Express JS source and this is the main module where express is exported
module.exports = createApplication;
function createApplication() {
var app = function(req, res, next) {
app.handle(req, res, next);
};
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false);
// expose the prototype that will get set on requests
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
// expose the prototype that will get set on responses
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
app.init();
return app;
}
I am confused about this piece of code
var app = function(req, res, next) {
app.handle(req, res, next);
};
The variable app is assigned and used inside the function at the same time. How can this work? There is no definition of an app anywhere else. Find the real source here.

The function is created and assigned to the app variable. That's a normal function expression assignment.
Then, the two mixin() lines add methods to the app function. So, after calling those functions, it has things like app.handle() and app.init().
Then, two more properties app.request and app.response are added.
Then, app.init() is called.
Then, sometime later the app function is called (when an http request arrives) and when it is called, it calls app.handle() which is just calling a function that is a property of itself. That's all legit. It would be similar to calling this.handle() in a more traditional object.
Here's a little demo of the part that seems to have you most confused:
var test = function() {
test.doSomething();
}
test.doSomething = function() {
console.log("doSomething");
}
test(); // causes test.doSomething() to get called

Related

Backbone Marionette middleware only runs on first route load

I am trying to add some middleware to Marionette's extended version of Backbone's router. Here's my code.
AppName.Router = Backbone.Marionette.AppRouter.extend({
appRoutes:{
// routes
},
route: function(route, name, callback) {
var router = this;
if (!callback) {
callback = this[name];
}
var middleware = function() {
console.log('in middleware');
callback.apply(router, arguments);
};
return Backbone.Router.prototype.route.call(this, route, name, middleware);
}
});
What I think should be happening is whenever I load a route, the console prints 'in middleware'.
What is happening is whenever I load the first route and only the first route, the console prints 'in middleware'.
I researched by using the top solution on this question and these are the results that I get.
Edit: I have also tried 'execute' as specified in the documentation and have had the same results.

Issue passing data to child routes in Node.js

Im new to Node.js and keep getting the Error: Route.get() requires callback functions but got a [object Undefined] error
and Ive checked out the following question and either dont understand or im still doing something wrong
Express routes: .get() requires callback functions but got a [object Object]
.get() requires callback functions but got a [object Undefined]
Error: Route.get() requires callback functions but got a [object Undefined]
Node Route.get() requires callback function but got a [object undefined]
my file structure is
server.js
routes/api/geolocations.js
routes/api/geolocations/regions.js
routes/api/geolocations/destination.js
ROOT: server.js
var geolocation = require('./routes/api/geolocation')(app);
app.get('/geolocation/', geolocation.delegate);
then I pass my data to routes/api/geolocations.js by using
geolocation.delegate(unparsedData);
from there I parse the data and send it down it's appropriate child routes.
PARENT: geolocations.js in my routes/api/geolocations.js
var destination = require('./geolocations/destination');
var region = require('./geolocations/region');
module.exports = function(app) {
return {
app.get('./geolocation/region', region.delegate);
app.get('./geolocation/destination', destination.delegate);
delegate: function(unparsedData, req, res) {
var data =[setup package for child states using unparsedData]
//HERE Id like to pass the new `data` to region or destination using the following
region.delegate(data);
//OR
destination.delegate(data);
CHILDREN: region.js / destination.js in routes/api/geolocations/regions.js or routes/api/geolocations/destination.js
module.exports = function(app) {
return {
delegate: function(data, req, res) {
...do stuff
}
}
}
UPDATE: I guess I dont know where to set up my routes, in server.js or if i can in geoloaction.js, does it matter, do need to do something like this in server.js?
var regions = require('./routes/api/geolocation/regions')([pass stuff here]);
geolocation.get('./routes/api/geolocation/regions', regions.delegate);
You should use express.js easy setup and run.
Simply download IntelliJ IDEA, find free version, then install. Then run the application and goto File->Setting->Plugin and search for NodeJS then install. Followed to this you need to Enable it. To do this goto File->Setting->Language & Frameworks->open arrow-> JavaScriptopen arrow->Libraries->Enable Node.js Core.
File Structure
routes/api/geolocations.js
routes/api/geolocations/regions.js
routes/api/geolocations/destination.js
You can have a look at the below code that might help you get started.
//------------------------------------------------------------------------
var express = require('express');
var router = express.Router();
var regions = require('../api/geolocations/regions');
var destination = require('../api/geolocations/destination');
//------------------------------------------------------------------------
//------------------------------------------------------------------------
/* geolocation.js */
router.get('/', function(req, res, next) {
var region_ext = regions.to_export;
var destin_ext = destination.to_export;
res.render('index', {
title: 'Geolocation',
region: region_ext,
destination:destin_ext
});
});
module.exports = router;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
/* region.js */
var to_export = function () {
return 'this is from regions';
}
module.exports.to_export = to_export();
//------------------------------------------------------------------------
//------------------------------------------------------------------------
/* destination.js */
var to_export = function () {
return 'this is from destination';
}
module.exports.to_export = to_export();
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//In app.js, just change
var routes = require('./routes/api/geolocations');
//------------------------------------------------------------------------
jfriend00 is right, You got a little mess there. Maybe you should consider make use of next(), since if you use it the other middlewares will have a chance of manipulating the request.

Using epilogue, is it possible to get back a resource without associations?

I have
epilogue.resource({
model: db.Question,
endpoints: ['/api/questions', '/api/questions/:id'],
associations: true
});
So when I hit /api/questions, I get back all the associations with the resources. Is there something I can pass to not get the associations in certain cases? Or should I create a new endpoint:
epilogue.resource({
model: db.Question,
endpoints: ['/api/questions2', '/api/questions2/:id']
});
One way of doing is by using milestones you can define milestone for list and read behaviour in certain case, you have access to req object so you can do changes accordingly
https://github.com/dchester/epilogue#customize-behavior
Here is an example of list call modification
// my-middleware.js
module.exports = {
list: {
write: {
before: function(req, res, context) {
// modify data before writing list data
return context.continue;
},
action: function(req, res, context) {
// change behavior of actually writing the data
return context.continue;
},
after: function(req, res, context) {
// set some sort of flag after writing list data
return context.continue;
}
}
}
};
// my-app.js
var epilogue = require('epilogue'),
restMiddleware = require('my-middleware');
epilogue.initialize({
app: app,
sequelize: sequelize
});
var userResource = epilogue.resource({
model: User,
endpoints: ['/users', '/users/:id']
});
userResource.use(restMiddleware);

Meteor CollectionFS Collection is Undefined?

I am trying to use CollectionFS and GridFS to upload some images to my app and serve them back.
I have the following definitions:
ImageStore.js:
var imageStore = new FS.Store.GridFS("images", {
mongoUrl: 'mongodb://127.0.0.1:27017/test/',
transformWrite: myTransformWriteFunction,
transformRead: myTransformReadFunction,
maxTries: 1,
chunkSize: 1024*1024
});
EventImages = new FS.Collection("images", {
stores: [imageStore]
});
ImageStorePub.js:
Meteor.publish("EventImages", function() {
return EventImages.find();
});
ImageUploadHandler.js:
if (Meteor.isServer) {
EventImages.allow({
'insert': function() {
// add custom authentication code here
return true;
}
});
}
After typing all of this I tried wrapping them all in a if(Meteor.isServer){...} despite the fact that they're already in my server folder, but my app is still crashing due to error ReferenceError: EventImages is not defined
at server/route handlers/ImageUploadHandler.js:2:1
I made a mistake in not assigning the variable on both the client and server.

ExpressJS why is my GET method called after my DELETE method?

In my express app, when the DELETE method below is called, the GET method is immediately called after and it's giving me an error in my angular code that says it is expected an object but got an array.
Why is my GET method being called when i'm explicitly doing res.send(204); in my DELETE method and how can I fix this?
Server console:
DELETE /notes/5357ff1d91340db03d000001 204 4ms
GET /notes 200 2ms - 2b
Express Note route
exports.get = function (db) {
return function (req, res) {
var collection = db.get('notes');
collection.find({}, {}, function (e, docs) {
res.send(docs);
});
};
};
exports.delete = function(db) {
return function(req, res) {
var note_id = req.params.id;
var collection = db.get('notes');
collection.remove(
{ _id: note_id },
function(err, doc) {
// If it failed, return error
if (err) {
res.send("There was a problem deleting that note from the database.");
} else {
console.log('were in delete success');
res.send(204);
}
}
);
}
}
app.js
var note = require('./routes/note.js');
app.get('/notes', note.get(db));
app.post('/notes', note.create(db));
app.put('/notes/:id', note.update(db));
app.delete('/notes/:id', note.delete(db));
angularjs controller
$scope.delete = function(note_id) {
var note = noteService.get();
note.$delete({id: note_id});
}
angularjs noteService
angular.module('express_example').factory('noteService',function($resource, SETTINGS) {
return $resource(SETTINGS.base + '/notes/:id', { id: '#id' },
{
//query: { method: 'GET', isArray: true },
//create: { method: 'POST', isArray: true },
update: { method: 'PUT' }
//delete: { method: 'DELETE', isArray: true }
});
});
** UPDATE **
To help paint the picture, here's the angular error i'm getting:
Error: [$resource:badcfg] Error in resource configuration. Expected response to contain an object but got an array http://errors.angularjs.org/1.2.16/$resource/badcfg?p0=object&p1=array
I'm assuming that i'm getting this error because my delete method is calling my get method (somehow) and the get method returns the entire collection.
Server side
You're removing an element from a collection in your delete function. This is done asynchronously and calling your callback when it's finished.
During this time, other requests are executed, this is why your GET request is executed before your DELETE request is finished.
The same happens in your get function, you're trying to find an element from a collection and this function is too asynchronous.
But this is server side only and it is fine, it should work this way, your problem is located client side.
Client side
If you want to delete your note after you got it, you will have to use a callback function in your angular controller which will be called only when you got your note (if you need help on that, show us your noteService angular code).
This is some basic javascript understanding problem, actions are often made asynchronously and you need callbacks to have an execution chain.
Maybe try doing something like this:
$scope.delete = function(note_id) {
var note = noteService.get({ id: note_id }, function()
{
note.$delete();
});
}
Your code doesn't make sense though, why is there a get in the $scope.delete? Why not do as simply as following:
$scope.delete = function(note_id) {
noteService.delete({ id: note_id });
}
Error
I think you get this error because of what your server sends in your exports.delete function. You're sending a string or no content at all when angular expects an object (a REST API never sends strings). You should send something like that:
res.send({
results: [],
errors: [
"Your error"
]
});

Categories

Resources