My business logic includes mongodb operations and redis operations on one request. I do not know where we should put logic code to. In Java project, we have DAO, service and controler objects. but in nodejs projects, I don't know where to put my code. shall I put logic code to routes/index.js?
app.post('/deal', function(req, res) {
... //TODO: here
});
or create a kind of service objects such as what we do in Java proejct?
Here's a question that might help: Mongoose-based app architecture
You should also look at the http://mean.io stack, as their templates will show you how to best structure your app, including where to store your logic.
Related
I am working to create a serverless REST API via Firebase Cloud Functions, which seems to work well but the examples and documentation all seem to use a monolithic solution, since they use the Express framework and essentially map the root http request to the Express app, then let it handle the routing. I understand that this is because the Firebase Hosting platform does not have the ability to handle http verbs.
My expectation was that a serverless / FaaS approach would have a function for each endpoint, making for easy updates in future since there's no need to update the whole app, just that single service - i.e. a more functional approach.
What am I missing here? Why is the approach to use a single function to contain an express app? Doesn't this defeat the purpose of a serverless / Cloud Functions approach? And is there any other way of doing this?
The documentation shows how to create an endpoint without the help of an Express app, router, or middleware:
exports.date = functions.https.onRequest((req, res) => {
// ...
});
All you have to do is arrange to send a response with res.send(...) or similar.
I'm new to Sails, but have used Express, and am considering Sails for my upcoming project. I particularly like that it makes the CRUD API for me and connects Socket.io automatically.
The next application I'm planning to work on has an indeterminate size; if it works well, we want to separate our CRUD/JSON API from our Web/HTTP server and load balance the Web/HTTP server. This would allow us to utilize the CRUD/JSON API in other adjacent applications, like code for statistical analysis, or external data parsers which import data, or other things which have nothing to do with Web/HTTP servicing.
In express I would consider making the API section a module then export the express.router with all the api calls like so
//appAPI.js
var routes = require('express').router();
routes.get('/user/:id', function(request, reply){
// assume db is connected database object
// and request.params.id is as expected
db.getUser(request.params.id, function(u){
reply.json(u);
});
})
module.exports = routes;
//app.js
var app = require('express')(),
api = require('appAPI');
app.use('/api', api);
Then in my application, if I want to separate the Web from the API, I can package up the appAPI.js, and associated model code, and make a small connector to redirect all routes /api/* to the ip address and port of the api server, or other possibilities.
Can I do something like this in Sails? It seems that the automated model creation and the socket.io automation would make this difficult. Alternatively, I might be able to make a module for the API with a whole sails server then embed it in the main Web/HTTP server, which has its own sails objects running, but this seems like it either would not work, break the socket.io connections, or work, but be horribly inefficient as it would have multiple instances of sails running.
Any recommendations would be helpful and I'm willing to consider alternative ways of working this. Thank you all for any help you might provide and have a wonderful day.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I would like to know the structure of a typical NodeJS app, because the more I read and see the projects, the more confused I am, specifically for questions like these (or even more after I updated this question):
Take the MEAN stack for example, from what I know, NodeJS and Express take care of the server part, providing the server interface, etc. MongoDB and Angular are pretty straightforward.
But where should the business logic go? Say if I have a controller.js which contains a function, and the route.js file binds the request with this controller function. My question is: under which module these files belong to/run under (Express or NodeJS?)
Where is the starting point of a NodeJS app? Say index.php is the starting point of a PHP app, but where is it for NodeJS app? I can see that all Nodejs projects have a file called server.js or app.js, etc.(containing something like module.exports = app;) But how can NodeJS know which file to find and execute?
I am a fresh noob on NodeJS, Express, sequelize.js/Mongoose, Jade/EJS but want to get started on a NodeJS project. Could you please elaborate on the actual function that each modules provide and a general introduction of the typical structure for a full JS stacked NodeJS app? Thanks in advance!
Alright, this is a pretty broad question and I'm definitely no expert, but I'll do my best here.
TL;DR
routes are controllers that tell what logic to execute when a user navigates their browser to a certain path within your app, including which views to render and what data to send to those views
models are just that - data models within your application
module.exports = tells a file what exactly it "exports", that is what code needs to be executed or accessible from your main app file.
require(..) includes a module. You can set this on a variable so that you may call module functions later, or simply execute a function if that is all that module.exports returns.
Combining these techniques can help you nail down a solid framework for any of your applications.
Long Answer
Express provides a solid framework for structuring your Node.js application. Node is completely independent of Express, but because of how popular Express is they practically go hand-in-hand. Once installed, Express can be used to generate a scaffold web project (with options) for you to build on top of if you'd like.
Controllers
A generated project will create /routes/index.js, which (if you understand MVC) is essentially your main controller. A route in express is written as so:
app.get('/path', function(req, res, next){ .. } );
Lets break that down: our application variable (app) is being told that on a GET request to '/path' to execute an anonymous callback function with req, res, next variables (request, response, callback respectively). I find it helpful to think of this like a custom event handler.
Its important to note at this point that we could also call app.post with the same syntax for posts to a URL as opposed to gets.
Within our anonymous callback, we handle any incoming data and render a view for the user. This is where most of my business logic ends up, so it actually makes sense to NOT use anonymous functions here. Here's an example of a basic callback that just displays a homepage:
app.get('/', function(req, res, next){
//some business logic
res.render('views/home');
});
When the user tries to GET the index path of our application (/), we simply render our home view that, from the root of our project, is stored in a views folder.
But what if we want to modularize this so that we aren't declaring all of our routes in our main app.js or server.js?
We use module.exports = .. in our modules to tell our server what exactly to include. In my controller, I export a single function that takes the application as an argument and uses that to define our routes like so:
Controllers/User.js
module.exports = function(app){
app.get('/users', function(req, res){
var users = req.db.collection('users').find();
if (!users) {
console.log("no users found");
res.redirect('/');
} else {
res.render('users/index', {users : users});
}
});
};
Don't worry about the req.db code, I attach the database to the request in my application but that isn't done by default. Simply understand that I'm getting a list of 'users' here, and redirecting the user to the index of my app if there aren't any.
Models
Mongoose provides us with a great interface for writing models. With mongoose, writing models is a three step process:
Define a schema
Define model logic
Generate and export the model
Here is an example of a User model:
Models/User.js
var mongoose = require('mongoose'),
userSchema = new mongoose.Schema({
name: { type: String, required: true },
joinDate: {type: Date, default: date.now }
}),
User = mongoose.model('user', userSchema);
module.exports = user;
Server App
module.exports is used to help us define some modularity to our codebase. When we run a node application, we're ultimately running a single JavaScript file (you've already seen that file with server.js or app.js).
To keep this file from getting too big with multiple models and routes, we use require(module) to include code from other JS files. module in our case would be a path to the module we want to require. If you have the following doc structure:
| Controllers
- User.js
| Models
- User.js
| Views
app.js
To include your user controller from app.js, you would write: require('./Controllers/User'). Since our controller modules simply export functions, we can call that function immediately after our require statement by simply adding parentheses at the end (with whatever parameters are required). Including my controllers looks like so:
require('./Controllers/User')(app)
I'm passing in the actual app, because my module (below) simply exports a function that adds business logic to my app's routes. This only needs to be called and never used, so I don't capture my controller as a variable to call methods on later.
Including models is a little different, since we may want to perform some operation that our model defines. We can do this by changing up our require code just a bit:
var User = require('./Models/User');
Now we can call methods of our User model whenever. Mongoose gives us a lot of base functionality for free:
User.find({}, function(err, users){ .. });
The above function will go find all of our users, and then execute an anonymous function with a potential err (is null if no issues) and then a list of our users in JSON format. Pretty nifty.
Combining all of these concepts is how you create a basic web application using Express and Node.js. Please let me know in the comments if there's anything I can clarify about how I use Express. This is very surface level knowledge, and I suggest digging into documentation and looking at plugins to extend the capabilities of your apps. Good luck!
I would like to return localized Strings for multilanguage business objects in our RestFul API based on node.js, restify and mongoose. I have the requirement to store the translated resources on our translation resource server, but also need to support dynamic creation of those business objects.
I found a solution to easily plugin the i18n process in the POST/PUT calls using a single pre-'save' mongoose middleware on all Schema, when creating or updating my multi-languate business objects - this works because I am able to pass the request context to the obj.save(req, callback) call.
But, I am struggling to plug in the i18n on simple GETs. I thought of and tried different ways where I can plugin the i18n before returning the response, but don't really find a good way. Options I thought of:
translate in a mongoose middleware pre /post ('init'):
Problem: I don't have access to the request context, and therefore
don't know the locale to return, so I cannot translate there.
translate in the toObject() / toJSON {transform: }:
Same issue - i don't have the request context in these hooks.
translate in the handler/controller methods for each ressource.
Problem: Duplication, I have to do it everywhere, I would really prefer a solution I can define on the model/Schema layer
translate in a restify / express middleware towards the end:
Problem: I don't have access to the mongoose schema metainformation anymore, so I don't know which attriutes to translate.
Edit: just found this additional way:
- translate in a custom restify responseFormatter:
This seems to work nicely, in the reponseformatter I have access to everything I need. It kind of seems a little weird from an architechtural point of view, but if nobody has a better idea, I will add this as an answer.
Maybe (hopefully) I am missing something obvious...
thanks for any hints
The app is using express 3. Here is a barebones example of a route that fetches data from the database:
var Post = mongoose.model('Post')
app.get('post/:id/loompas', function(req, res) {
Post.getLoompas(function(err, data){
res.render('x', data)
})
})
Where Posts.getSomeData is defined as instance methods in /models/post.js, and sometimes accesses external APIs:
PostSchema.method('getLoompas', function(callback){
var post = this
API.get('y', function(x){
this.save(x)
callback(x)
})
})
This is starting to smell, and doesn't look like it belongs along the Schema definition. The collection of methods could grow quite large.
What design patterns are recommended to separate these concerns and avoid extremely fat models? A service layer for external API calls? Any interesting solutions out there?
This does indeed smell a little bit.
I would use the approach of considering your web app merely as a view of your application.
The best way to ensure this is to never use your mongoose models from your webapp. You could have your webapp living in a process and your model specific logic in another process. The job of that second process would be to take care of your business logic and persistence layer (mongoDB), making it the M in MVC.
Accessing external APIs would take place in that Model layer, we your can separate it from your persistence implementation.
There's a way of communicating between node processes that I like, it's dnode. Once set up, it looks like you are communicating with objects and callbacks within your own process. I would make the webapp and the business app communicating through this in order to get data. The webapp needn't manipulate the actual data and instead sends message to the Model layer (as described by the MVC pattern).
This ensures complete separation between controller/view (webapp) and model+persistence.
One side effect of this organization is that you can easily write other clients of your application, for example a CLI client or a RESTful API.
Are you trying to get id and somedata from url (post/:id/:somedata) ? to construct schema ?
Ideally one should use :
app.post('/reg', function(request, response){
console.log(request.body.name);
console.log(request.body.email);
...
}
which is when form is submitted on the 'reg' HTML form page, where you can set all the variables(name,email) in object. In app.post you can get the schema definition from the request itself without having to scan through the url to get variables.
If you still want to know how to get the variables from the url then do this in app.get:
vars=request.url.split('/');
//vars contains all the variables you have to use.
//use vars to create schema
After you get/create the schema directly pass it to the function / or iterate through the object elements calling that function.