上回我们说到,创建了一个极简的 Web 服务,监听了端口,设置了正确的编码,成功地在浏览器看到了返回的内容:你好,世界!
。
那么本章节呢,我们来详细分析上一章的代码,来学会:如何有效地查看官方文档
。
首先,要知道官方文档在哪里,Node.js 的官网地址是:https://nodejs.org
。
上图就是 Node.js 官网,箭头指向的地方,就是官方文档。
同时可以看到,在官网右侧,有一个简单的 web 服务写法示例,跟我们上一章的极简 Web 服务代码相差无几。
点击箭头处的 Docs
,来到了文档中心。
图中 (1) 处就是我们代码中创建一个 Web 服务用到的 HTTP 模块。(2) 处就是创建 Web 服务的 createServer 方法。
点击 (2) 处后,就能看到上图关于 createServer 方法的详细说明了。
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 服务发送问题:
- 我要一个 html 页面。
- 页面中有 js 脚本,我也要。
- 还有个 CSS 样式,我还要。
- 还有好几个图片,快给我。
服务器不断地向浏览器返回响应:
- html 页面给你了。
- js 也给你了。
- css 收到了吧。
- 给给给,图片。
天下武功,唯快不破。
浏览器和 Web 服务器之间一问一答的时间,只有几十毫秒。而且它们之间,一次性可以进行多个问答,所以才让我们看到了网页刷刷地一下就出来了,这就是我们每天上网冲浪的基础。
但是也有页面卡顿,白屏的时候,什么问题呢?无非就是网络慢,图片大,服务器迟迟没有返回数据,无外乎此。
那么继续回到文档的艺术,这个方法还没说完呢。
options 属性中,有这么一个参数:maxHeaderSize
,用来设置最大 Http 头消息大小,默认值是 16384
字节,也就是 16KB
。
让我们来干点坏事,把这个值设置为 1
。
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 服务器的最大请求头的限制,当然不会返回内容啦。
import { createServer } from 'node:http';
const server = createServer(
{
maxHeaderSize: 100000
},
(req, res) => {
res.end('你好,世界!');
}
);
server.listen(3000);
不信这个邪?我们改成 10 万看看。
重启服务,再次访问,又恢复正常了。
所以你能看到,每个属性,都有大大的作用,存在即有理,有时候你没有用到,不代表它没有作用。
说得也不少了,我们最后通过看官方文档的艺术,来做一个实践,当 Web 服务启动后,打印一串字符,“服务已启动,监听端口为:3000”
。
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() 方法,来到上图,只有短短的一行字:listen 方法跟 net 模块的 Server 方法的 listen 用法一样
。
再点击画圈处的函数。
就来到了 server.listen()
函数的定义处,可以看到有 4 种写法。
官网首页,用的就是第四种写法,用到了 3 个参数:端口
,主机地址
,回调函数
。
那么将我们的代码改为这种写法如下:
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.end('你好,世界!');
});
server.listen(3000, '127.0.0.1', () => {
console.log('服务已启动,监听端口为:3000');
});
至此,艺术已成。
通过查看官方文档,我们有理有据地调整了我们的代码,学会了 server.listen()
函数的不同用法。
之后的课程中,就不再分享如何看官方文档了,大家举一反三即可。
笔者自学的过程中,查阅官方文档的次数是最多的,它及时,准确,详细,权威。
当你掌握了看官方文档的艺术,很多问题都会迎刃而解。