Node入门

应用不同模块分析

HTTP服务器:
路由:
请求处理程序:接收数据 / 使用视图逻辑显示内容
请求数据处理功能:处理并转换POST数据

server.js中的HTTP服务器模块 index.js文件常去调用应用的其他模块

构建应用模块

一个基础的HTTP服务器

var http = require("http");

http.createServer(onRequest).listen(8888);

第一行请求(require)Node.js自带的 http 模块,并且把它赋值给 http 变量。

接下来我们调用http模块提供的函数: createServer 。这个函数会返回一个对象,这个对象有一个叫做 listen 的方法,这个方法有一个数值参数,指定这个HTTP服务器监听的端口号。

函数传递

在JavaScript中,一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。

为什么要用函数传递?

基于事件驱动的回调

http.createServer(onRequest).listen(8888);

使用 http.createServer 方法的作用: 1.接收请求 2.处理请求

1和2是异步的:请求任何时候都可能到达,但是我们的服务器却跑在一个单进程中。

2——Node.js程序中,当一个新的请求到达8888端口的时候,我们怎么控制流程呢?
回调。我们给某个方法传递了一个函数,这个方法在有相应事件发生时调用这个函数来进行 回调 。

1——在创建完服务器之后,即使没有HTTP请求进来、我们的回调函数也没有被调用的情况下,我们的代码还继续有效吗?
有效。这就是事件驱动的异步服务器端JavaScript和它的回调。

服务器如何处理请求?

也就是我们的回调函数 onRequest() 的主体部分。

function onRequest(request, response) {
  console.log("Request received.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

两个参数:
request 和 response ,是对象,可以使用它们的方法来处理请求。

request 对象的方法:
我们对请求的细节并不在意,所以没有使用。

response对象的方法:
response.writeHead() :发送一个HTTP状态200和HTTP头的内容类型(content-type)
response.write() :在HTTP相应主体中发送文本“Hello World"。

服务器的模块放在哪里?

模块:提供公共方法给本地变量
把某段代码变成模块意味着我们需要把我们希望提供其功能的部分 导出 到请求这个模块的脚本。

处理HTTP请求——“路由选择”

路由的数据来源

通过Node.JS的url和querystring模块,解析onRequest()回调函数的第一个参数request对象,从而可以通过请求的URL路径来区别不同请求了。

如何把路由和服务器整合起来?

1.通过硬编码的方式将这一依赖项绑定到服务器上
缺点:太费劲了?

2.使用依赖注入的方式较松散地添加路由模块
2.1 内容传递给服务器
2.2 服务器传递给内容(指requestHandlers.js)

不好的实现方式
“直截了当的实现方式”意思是:让请求处理程序通过onRequest函数直接返回(return())他们要展示给用户的信息。
问题:当未来有请求处理程序需要进行非阻塞的操作的时候,我们的应用就“挂”了。

阻塞与非阻塞
阻塞操作,形象的说就是“它阻塞了所有其他的处理工作”。

这显然是个问题,因为“在node中除了代码,所有一切都是并行执行的”。

这句话的意思是说,Node.js可以在不新增额外线程的情况下,依然可以对任务进行并行处理 —— Node.js是单线程的。它通过事件轮询(event loop)来实现并行操作,对此,我们应该要充分利用这一点 —— 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。

然而,要用非阻塞操作,我们需要使用回调,通过将函数作为参数传递给其他需要花时间做处理的函数(比方说,休眠10秒,或者查询数据库,又或者是进行大量的计算)。

对于Node.js来说,它是这样处理的:“嘿,probablyExpensiveFunction()(译者注:这里指的就是需要花时间处理的函数),你继续处理你的事情,我(Node.js线程)先不等你了,我继续去处理你后面的代码,请你提供一个callbackFunction(),等你处理完之后我会去调用该回调函数的,谢谢!”

非阻塞操作的不当使用:
异步回调
没看懂

实例应用

处理POST请求

采用异步回调来实现非阻塞地处理POST请求的数据:
因为POST请求一般都比较“重” —— 用户可能会输入大量的内容。用阻塞的方式处理大数据量的请求必然会导致用户操作的阻塞。

如何使之非阻塞?
Node.js会将POST数据拆分成很多小的数据块,然后通过触发特定的事件,将这些小数据块传递给回调函数.这里的特定的事件有data事件(表示新的小数据块到达了)以及end事件(表示所有的数据都已经接收完毕)。

如何在特定时间触发时,回调对应的函数?
通过在request对象上注册监听器(listener) 来实现。这里的request对象是每次接收到HTTP请求时候,都会把该对象传递给onRequest回调函数。

request.addListener("data", function(chunk) {
  // called when a new chunk of data was received
});

request.addListener("end", function() {
  // called when all chunks of data have been received
});

实现思路就是: 直接在服务器中处理POST数据,然后将最终的数据传递给请求路由和请求处理器,让他们来进行进一步的处理。
将data和end事件的回调函数直接放在服务器中,在data事件回调中收集所有的POST数据,当接收到所有数据,触发end事件后,其回调函数调用请求路由,并将数据传递给它,然后,请求路由再将该数据传递给请求处理程序。

处理文件上传

处理文件上传“就是”处理POST数据 —— 但是,麻烦的是在具体的处理细节,所以,这里采用现成的模块更合适点。

updatedupdated2024-07-162024-07-16