Node.js 入门 - 第 1 部分






4.79/5 (23投票s)
获取查询字符串数据、POST 数据,并使用序列化对象进行响应
George 的 Node.js 入门系列
- 第 1 部分:本文(Node.js 入门第 1 部分)
- 第 2 部分: 使用 Node.js 监控文件和文件夹中的更改
引言
欢迎来到我希望是一个关于学习和使用 Node.js 的长系列文章。计划是(如果工作和孩子允许)每月发表两篇文章。
本系列文章的格式是“与我一起学习”。这意味着什么?我对 Node.js 是新手,就像新到不能再新一样。我在其他技术方面有丰富的经验,但谈到 Node……就不那么多了。我建立了一个项目,包含几个冲刺,以便熟悉这项技术,我认为在每个冲刺完成后写一篇文章会很有趣。
我绝不是专家,我相信我会犯错误或多次违背最佳实践。我希望在我的小项目结束时,我(和你们)都能达到 Node 至少中级水平的专业知识,但我希望在一开始就绝对清楚:我不是专家,也不假装是,你们不应该将本系列文章视为来自专家的东西。
关于框架的说明
我很清楚有无数的框架可以完成我将在本系列中做的大部分(如果不是全部)工作。我没有“不在本地发明”综合症,我故意回避使用框架,直到我对底层环境有了更深入的了解,而且(在我看来)没有比通过困难的方式做到这一点更好的方法。我喜欢框架,我喜欢能够利用以前的工作并“完成工作”,但再次,在学习时我喜欢犯自己的错误……我发现这有助于我获得更扎实的核心知识。
冲刺 1 项目
最初的冲刺(本文的重点)相对简单。我希望能够:
- 创建一个 HTTP 服务器
- 确定传入请求的 IP
- 创建自定义模块
- 创建标准响应模块
- 将对象序列化为 JSON
- 将对象序列化为 XML
- 捕获查询字符串数据
- 捕获 POST 数据
- 以某种有意义的方式响应请求
那么,让我们开始吧!
Node.js
Node.js 是 Google V8 JavaScript 引擎的服务器端实现。您可以在 https://node.org.cn 找到有关 Node.js 的深入信息。我读过的每篇关于 Node 的文章都浪费了太多空间来描述 Node,它们都引用了该网站的信息,所以如果您不介意,我将直接将您指向那里。
环境
本系列文章目前针对 Node v.0.10.22。
Node 可以安装在 Windows、Linux 和 Macintosh 上。我的个人设置是安装了 Node 的 CentOS 虚拟机和安装了 Node 的 Windows 机器的组合。您可以通过 SSH 和 VI 在您的 Linux 机器上使用 Node,或者您可以安装 Microsoft 的 Visual Studio Node 扩展。我知道我可能会惹恼很多纯粹主义者,因为我讨厌 VI,而 Node 扩展非常棒,我强烈推荐它。我在 Visual Studio 中编写 Node 代码,然后将其传输到 CentOS 机器上运行。这对我来说很有效。
模块
Node 中的模块是一种将代码分成逻辑部分并按需使用它们的方式。Node(如他们所描述的)有一个使用 `requires` 关键字的简单模块加载系统。对于第一篇文章,我们将创建三个自定义模块来满足第一次冲刺的要求。
FieldParser 模块
`FieldParser` 模块处理从请求对象解析 `POST` 和 `GET` 数据。对于查询字符串数据,这非常简单,因为它是一次性发送过来的,但是,`POST` 数据是分块发送的,所以我们将不得不处理它并在解析完成后触发一个事件。
为了处理事件,我们必须从 `EventEmitter` 类继承。您可以手动执行此操作,也可以使用原生 node 模块 `util` 中的 `inherits` 方法。
`FieldParser` 模块是第一篇文章中唯一关注事件的模块,它将使用 `module.exports` 方法导出一个 `FieldParser` 对象。
`FieldParser` 具有以下方法/属性。
- `method`:从请求中检测到的方法,可以是 `POST`、`GET` 或 `GETPOST`(同时发送查询字符串和 POST 数据)
- `fields`:解析字段的集合
- `queryFields`:解析查询字符串字段的集合(无 POST 字段)
- `fieldCount`:解析字段的数量
当方法是 `POST` 时,`fields` 集合将包含所有 POST 字段,`queryFields` 集合将为空。
当方法是 `GET` 时,`fields` 和 `queryFields` 集合都将填充相同的数据。
当方法是 `GETPOST`(同时提交查询字符串和 POST 数据)时,`fields` 集合将包含 `POST` 字段,`queryFields` 集合将包含查询字符串解析字段。
解析将在调用 `parse` 方法时开始,当对象触发“parsed”事件时,它将指示解析已完成。
`FieldParser` 模块的代码可以在附加的 zip 文件中的 /modules 目录下找到。XMLSerializer 模块
`XMLSerializer` 模块处理将 JavaScript 对象序列化为 XML。它相当基础,可能(肯定)需要改进,但对于第一个版本,以及为了满足冲刺 1 的要求,我认为它运行良好。
`XMLSerializer` 模块导出一个单一方法:`serialize(name, obj, encoding)`。此方法接受三个参数。
- 要用作序列化输出的父节点标签名称的对象 `name`(`string`)(必填)。
- 要序列化对象本身 (`obj`) (必填)
- XML 输出的 `encoding` (utf-8, utf-16, us-ascii, 等)
`serialize` 方法将返回一个表示序列化对象的 `string`。这是即时的,并且没有触发事件来指示它已完成(与 `FieldParser` 模块不同)。
`XMLSerializer` 模块的代码可以在附加的 zip 文件中的 /modules 目录下找到。
SerialResponse 模块
`SerialResponse` 模块是一个用于处理向请求客户端发送标准化序列化响应的模块。我想要一个可以包含标准状态返回以及序列化对象有效负载的东西。因此,`SerialResponse` 模块公开了以下内容:
- `XMLResponse(res, code, payload, what)` 方法。它将序列化的 XML 对象写入响应。此方法接受以下参数:
- `res`:要写入的响应对象
- `code`:ResponseCode 状态对象的数字代码
- `payload`:要序列化的有效负载对象
- `what`:有效负载对象的字符串描述
JSON Response(res, code, payload, what) 方法。它将序列化的 JSON 对象写入响应。此方法接受以下参数:
- `res`:要写入的响应对象
- `code`:`ResponseCode` 状态对象的数字代码
- `payload`:要序列化的有效负载对象
- `what`:有效负载对象的字符串描述
- `setCode(code, description, level)` 此方法在 `SerialResponse` 模块的 `codeDictionary` 集合中添加或设置值。有两个标准 `ResponseCodes`:`0` 和 `1`。`0` = OK,并且 `level` 为“`OK`”;`1` = 传递的响应代码无效,并且 `level` 为“`WARN`”。如果您愿意,可以将响应代码视为退出代码。在后续文章中,我将使用此概念。
- `dictionary`:此方法只返回 `codeDictionary`,如果您想查看其中有什么。
任何时候我们使用 `SerialResponse` 方法 `XMLResponse`、`XMLResponseWrite`、`JSONResponse` 或 `JSONResponseWrite`,它将输出一个 `string`,表示一个序列化对象,该对象是包含以下内容的整体序列化对象的一部分:
- - `status`:一个状态码对象(独立于 http 响应码),它返回一个数字码、一个描述和一个响应级别,指示返回对象的状态。推荐的级别是“`OK`”、“`WARN`”和“`ERROR`”。可以使用 `setCode` 方法将自定义代码添加到 `codeDictionary` 中。
- - `what`:有效负载对象的字符串描述。
- - `payload`:您返回给请求客户端的序列化对象。
注意:`SerialResponse` 模块依赖于 `XMLSerializer` 模块。
`SerialResponse` 模块的代码可以在附加的 zip 文件中的 /modules 目录下找到。
Using the Code
好的,现在我们已经花了很多时间来描述这个应用程序的自定义模块(我希望您已经仔细阅读了所附的代码),让我们将它们全部组合成一个基本的 Node.js 服务器应用程序,它从客户端接收一些输入并将其重复返回给我们。在后续文章中,我们将探索实际使用这些数据,而不仅仅是概念验证。但目前,本次练习的目的是能够满足冲刺 1 的要求。
导入我们将需要的模块。
此应用将需要三个模块。
- `http` 模块,Node 世界中处理 http 的地方(这将使我们能够创建监听器/服务器)。
- `FieldParser` 模块,我们可以在其中解析传入的 `get` 和 `post` 数据。
- 最后,`SerialResponse` 模块,我们可以在其中进行标准响应处理。
注意:`FieldParser` 和 `SerialResponse` 模块是我们自己编写的自定义模块,它们位于 /modules 目录中,因此当我们 `require()`(导入)它们时,我们必须使用 ./modules/ 作为前缀来描述它们的路径。
var http = require("http");
var fieldparser = require("./modules/FieldParser.js");
var serializedresponse = require("./modules/SerialResponse.js");
让我们知道服务器已启动。
console.log("Server Started");
创建服务器本身
我们将把服务器创建为一个变量,它监听请求和响应。我们将在创建服务器变量后设置实际的监听。在这里我们将获取提交的数据,解析它,并响应回去。请注意,我们是使用事件来完成的。解析器是异步的,我们知道解析完成的唯一方法是等待解析事件被触发。(似乎 Node.js 的所有内容都是异步的。他们称之为非阻塞,但我还不完全确定这目前的全部含义。)
var server = http.createServer(function(req, res) {
// let me know a request came in.
console.log("Received Request From : " + req.connection.remoteAddress);
// create a new fieldparser to parse the request
// for fields.<br /> var fp = new fieldparser();
// start listening to the request to parse it.
fp.parse(req);
// when parsing is done:
fp.on("parsed", function() {
serializedresponse.XMLResponse(res, 0, fp, "parsed fields");
})
});
将服务器设置为监听端口 3000
如果我们不将服务器设置为监听特定端口(在此例中为 3000),那么 Node 将会退出并终止。之所以会发生这种情况,是因为 Node 仅在有事情要做时才会运行……比如监听请求。如果没有事情可做,应用程序就会终止,你就完成了。
server.listen(3000);
测试(玩转它)
此时,您需要运行您的 Node 应用程序。您可以通过在存放所有附加文件的目录中键入“`node app.js`”从命令行运行,或者如果您正在使用 VisualStudio node 扩展,请按“F5”运行。
我已在 zip 包中包含一个小型 test.html 文件,允许您向新服务器发布数据。假设您在 test.html 文件中使用“`GET`”表单,并在字段一中提交“`Hello`”,在字段二中提交“`World`”,在文本区域中提交“`Aint this Great`”,您应该会收到一个如下所示的响应……
从现在开始,我建议您使用附加的代码,尝试 `JSONResponse` 或 `JSONResponseWrite`。我期待您的反馈。
我不得不多次大量删减这篇文章,但我希望它有所帮助。