想要清楚地了解 NodeJS 应用程序结构(完整的 JavaScript 堆栈)[关闭]

Posted

技术标签:

【中文标题】想要清楚地了解 NodeJS 应用程序结构(完整的 JavaScript 堆栈)[关闭]【英文标题】:Want to get crystal clear about NodeJS app structure (Full JavaScript Stack) [closed] 【发布时间】:2014-03-16 20:51:55 【问题描述】:

我想知道一个典型的 NodeJS 应用程序的结构,因为我阅读和查看项目的次数越多,我就越困惑,特别是对于这样的问题(甚至在我更新这个问题之后更是如此):

    以 MEAN 堆栈为例,据我所知,NodeJS 和 Express 负责服务器部分,提供服务器接口等。MongoDB 和 Angular 非常简单。

    但是业务逻辑应该去哪里呢?假设我有一个包含函数的controller.js,并且route.js 文件将请求与此控制器函数绑定。我的问题是:这些文件属于/在哪个模块下运行(Express 还是 NodeJS?)

    NodeJS 应用的起点在哪里?假设index.php 是 PHP 应用程序的起点,但 NodeJS 应用程序的起点在哪里?我可以看到所有Nodejs项目都有一个名为server.jsapp.js等的文件(包含module.exports = app;之类的东西)但是NodeJS如何知道要查找和执行哪个文件?

我是 NodeJS、Express、sequelize.js/Mongoose、Jade/EJS 的新手,但想开始一个 NodeJS 项目。您能否详细说明每个模块提供的实际功能以及完整的 JS 堆叠 NodeJS 应用程序的典型结构的一般介绍?提前致谢!

【问题讨论】:

【参考方案1】:

好的,这是一个相当广泛的问题,我绝对不是专家,但我会在这里尽力而为。

TL;DR

routes 是控制器,当用户将浏览器导航到应用程序中的特定路径时,它们会告诉执行什么逻辑,包括要呈现哪些视图以及要向这些视图发送哪些数据 models 就是这样 - 应用程序中的数据模型 module.exports = 告诉文件它“导出”的确切内容,即需要执行或从您的主应用文件访问的代码。 require(..) 包含一个模块。您可以在变量上设置它,以便稍后调用模块函数,或者如果这是module.exports 返回的全部,则只需执行一个函数。

结合使用这些技术可以帮助您为任何应用程序确定一个可靠的框架。


长答案

Express 为构建 Node.js 应用程序提供了一个可靠的框架。 Node 完全独立于 Express,但由于 Express 的受欢迎程度,它们实际上是齐头并进的。安装后,Express 可用于生成一个脚手架 Web 项目(带有选项),如果您愿意,您可以在其上构建。

控制器

生成的项目将创建/routes/index.js,它(如果您了解 MVC)本质上是您的主要控制器。 express 中的路由是这样写的:

app.get('/path', function(req, res, next) ..  );

让我们分解一下:我们的应用程序变量 (app) 被告知在对 '/path' 的 GET 请求中执行带有 req, res, next 变量(分别为请求、响应和回调)的匿名回调函数。我发现将其视为自定义事件处理程序很有帮助。

在这一点上需要注意的是,我们也可以使用相同的语法调用app.post,而不是gets。

在我们的匿名回调中,我们处理任何传入数据并为用户呈现视图。这是我的大部分业务逻辑的最终结果,因此这里不使用匿名函数实际上是有意义的。下面是一个只显示主页的基本回调示例:

app.get('/', function(req, res, next)

    //some business logic

    res.render('views/home');
);

当用户尝试获取我们应用程序的索引路径 (/) 时,我们只需渲染我们的 home 视图,该视图从项目的根目录存储在 views 文件夹中。

但是,如果我们想要将其模块化,这样我们就不会在我们的主要 app.jsserver.js 中声明我们的所有路由?

我们在模块中使用module.exports = .. 来告诉我们的服务器究竟要包含什么。在我的控制器中,我导出了一个函数,该函数将应用程序作为参数并使用它来定义我们的路由,如下所示:

控制器/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);
        
    );

;

不用担心req.db 代码,我将数据库附加到我的应用程序中的请求,但默认情况下不会这样做。简单理解我在这里得到一个“用户”列表,如果没有的话,将用户重定向到我的应用程序的索引。

模型

Mongoose 为我们提供了一个很好的模型编写界面。使用 mongoose,编写模型是一个三步过程:

定义架构 定义模型逻辑 生成并导出模型

这是User 模型的示例:

模型/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;

服务器应用

module.exports 用于帮助我们为代码库定义一些模块化。当我们运行一个节点应用程序时,我们最终会运行一个 javascript 文件(您已经看到带有 server.jsapp.js 的文件)。

为了防止这个文件因多个模型和路由而变得过大,我们使用require(module) 来包含来自其他 JS 文件的代码。 module 在我们的例子中是我们想要的模块的路径。如果您有以下文档结构:

| Controllers
    - User.js
| Models
    - User.js
| Views
app.js

要包含来自app.js 的用户控制器,您可以编写:require('./Controllers/User')。由于我们的控制器模块只是导出函数,因此我们可以在 require 语句之后立即调用该函数,只需在末尾添加括号(使用所需的任何参数)。包括我的控制器看起来像这样:

require('./Controllers/User')(app)

我正在传递实际的应用程序,因为我的模块(如下)只是导出了一个函数,该函数将业务逻​​辑添加到我的应用程序的路由中。这只需要被调用并且从不使用,所以我不会将我的控制器捕获为变量以便稍后调用方法。

包含模型有点不同,因为我们可能想要执行模型定义的一些操作。我们可以通过稍微修改一下我们的需求代码来做到这一点:

var User = require('./Models/User');

现在我们可以随时调用 User 模型的方法。 Mongoose 免费为我们提供了许多基本功能:

User.find(, function(err, users) .. );

上面的函数会找到我们所有的用户,然后执行一个匿名函数,可能是err(如果没有问题,则为空),然后是JSON格式的用户列表。很漂亮。

结合所有这些概念,您可以使用 Express 和 Node.js 创建一个基本的 Web 应用程序。如果有任何关于我如何使用 Express 的说明,请在 cmets 中告诉我。这是非常表面的知识,我建议深入研究文档并查看插件以扩展您的应用程序的功能。祝你好运!

【讨论】:

注意:这就是我构建 Node 应用程序的方式。我知道这是一个非常主观的概念,所以其他人请随时提出改进建议。说到 Node,我自己还是个新手。 感谢您的明确回答。我想我现在可以明白了。干杯。

以上是关于想要清楚地了解 NodeJS 应用程序结构(完整的 JavaScript 堆栈)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

让我清楚地了解 Oracle 9i 中的外部联接

Nodejs 事件循环

软件评测师笔记_结构化需求分析法20161019

Java基础系列5:深入理解Java异常体系

didSelectRowatIndexPath 中的 UITableView 行数

nodejs的良好依赖注入模块