Skip to content

上回我们说到,创建了一个极简的 Web 服务,监听了端口,设置了正确的编码,成功地在浏览器看到了返回的内容:你好,世界!

那么本章节呢,我们来详细分析上一章的代码,来学会:如何有效地查看官方文档

首先,要知道官方文档在哪里,Node.js 的官网地址是:https://nodejs.org

官方文档主页

上图就是 Node.js 官网,箭头指向的地方,就是官方文档。

同时可以看到,在官网右侧,有一个简单的 web 服务写法示例,跟我们上一章的极简 Web 服务代码相差无几。

Node.js官方文档

点击箭头处的 Docs,来到了文档中心。

图中 (1) 处就是我们代码中创建一个 Web 服务用到的 HTTP 模块。(2) 处就是创建 Web 服务的 createServer 方法。

createServer方法

点击 (2) 处后,就能看到上图关于 createServer 方法的详细说明了。

js
import { createServer } from 'node:http';

const server = createServer((req, res) => {
    res.end('你好,世界!');
});

server.listen(3000);

为方便对比,我们把上节课的代码放到这。

那么我们可以看到,createServer 方法是有 2 个参数的,分别是 (1) 处的 options 和 (2) 处的 requestListener。箭头所指,就是这 2 个参数的对应内容。

你可以这么理解,如果把 Web 服务比做一个 “机器人”,那么 options 就用来描述它的身高,体重,颜色,最多能待机多久,最大能携带多少的重物,多久没回答你的问题算超时等等。

而 requestListener,则表示机器人接受到来自触觉,视觉,听觉的数据后,该如何处理进行反馈。所以你看,极简 Web 的例子中是不是当收到请求后,设置为不会产生乱码的编码,然后返回 “你好,世界!” 呢。

这就是请求和响应,也可以叫做一问一答。Web 服务就是建立在一问一答的基础上的。

浏览器不断地向 Web 服务发送问题:

  1. 我要一个 html 页面。
  2. 页面中有 js 脚本,我也要。
  3. 还有个 CSS 样式,我还要。
  4. 还有好几个图片,快给我。

服务器不断地向浏览器返回响应:

  1. html 页面给你了。
  2. js 也给你了。
  3. css 收到了吧。
  4. 给给给,图片。

天下武功,唯快不破。

浏览器和 Web 服务器之间一问一答的时间,只有几十毫秒。而且它们之间,一次性可以进行多个问答,所以才让我们看到了网页刷刷地一下就出来了,这就是我们每天上网冲浪的基础。

但是也有页面卡顿,白屏的时候,什么问题呢?无非就是网络慢,图片大,服务器迟迟没有返回数据,无外乎此。

那么继续回到文档的艺术,这个方法还没说完呢。

maxHeaderSize参数

options 属性中,有这么一个参数:maxHeaderSize,用来设置最大 Http 头消息大小,默认值是 16384 字节,也就是 16KB

让我们来干点坏事,把这个值设置为 1

js
import { createServer } from 'node:http';

const server = createServer(
    {
        maxHeaderSize: 1
    },
    (req, res) => {
        res.end('你好,世界!');
    }
);

server.listen(3000);

记得,重新启动服务,然后到浏览器访问。

网页报错提示

咦,怎么不返回:“你好,世界!” 了。

而且在红色划线处,有个 431 的 Http 错误码,这是什么意思呢?我们来看看官方解释:

431 http 状态码

请求内容首部太大

原因就是,请求内容首部太大啦。什么是请求首部呢?简单说一下,更多细节呢,请到笔者的问答群交流,不然这本小册,得变成大册。

控制台查看请求

如上图,其中 (6) 处就是头部,就是一问一答中的 “问”,(7) 处就是 Web 服务器的响应,就是一问一答中的 “答”。那个大的方框框住的,就是 maxHeaderSize 属性的管辖范围了。这么多字摆在这,明显大于我们服务器设置的 1 个字节,超出了 web 服务器的最大请求头的限制,当然不会返回内容啦。

js
import { createServer } from 'node:http';

const server = createServer(
    {
        maxHeaderSize: 100000
    },
    (req, res) => {
        res.end('你好,世界!');
    }
);

server.listen(3000);

不信这个邪?我们改成 10 万看看。

最大请求头改成10万

重启服务,再次访问,又恢复正常了。

所以你能看到,每个属性,都有大大的作用,存在即有理,有时候你没有用到,不代表它没有作用。

说得也不少了,我们最后通过看官方文档的艺术,来做一个实践,当 Web 服务启动后,打印一串字符,“服务已启动,监听端口为:3000”

js
import { createServer } from 'node:http';

const server = createServer((req, res) => {
    res.end('你好,世界!');
});

server.listen(3000);

console.log('服务已启动,监听端口为:3000');

简单,完事。

问题倒不大,但是呢,不太正规。

返回实例

我们继续看官方文档,createServer 执行后,返回了一个什么呢?是一个 Server 实例。

查看实例

点击此处,我们去一探究竟,原来是一个 Server 类。我们的代码怎么写的?const server = createServer()。是不是把 Server 类实例化后赋值给了 server,那么这个 server 就具备了所有 Server 这个类的属性和方法。

实例方法和属性列表

文档往回拉,拉到开头处,找到 Server 类,在这里我们可以一览全貌,所有的属性和方法,尽收眼底。同时,也可以看到我们代码中用到的 server.listen(3000) 方法。

server.listen()方法说明

点击 server.listen() 方法,来到上图,只有短短的一行字:listen 方法跟 net 模块的 Server 方法的 listen 用法一样

再点击画圈处的函数。

listen函数的写法

就来到了 server.listen() 函数的定义处,可以看到有 4 种写法。

官网首页,用的就是第四种写法,用到了 3 个参数:端口主机地址回调函数

那么将我们的代码改为这种写法如下:

js
import { createServer } from 'node:http';

const server = createServer((req, res) => {
    res.end('你好,世界!');
});

server.listen(3000, '127.0.0.1', () => {
    console.log('服务已启动,监听端口为:3000');
});

至此,艺术已成。

通过查看官方文档,我们有理有据地调整了我们的代码,学会了 server.listen() 函数的不同用法。

之后的课程中,就不再分享如何看官方文档了,大家举一反三即可。

笔者自学的过程中,查阅官方文档的次数是最多的,它及时,准确,详细,权威。

当你掌握了看官方文档的艺术,很多问题都会迎刃而解。

何以解忧,唯有代码。不忘初心,方得始终。