上回我们说到啊,创建了一个极简的 Web 服务,监听了端口,设置了正确的编码,成功地在浏览器看到了返回的内容 "你好,世界!"。
那么本章节呢,我们通过一个简单的例子来分析,如何有效地查看官方文档。
首先,要知道官方文档在哪里,Node.js 的官网地址是 https://nodejs.org。
点击箭头指向的地方,就是官方文档。
(1) 处就是我们代码中创建一个 Web 服务用到的 HTTP 模块。(2) 处就是用到的创建 Web 服务的 createServer 方法。
点击 (2) 处后,就能看到上图关于 createServer 方法的详细说明了。
为方便对比,我们把上节课的代码放到这。
可以发现,(3) 处和 (4) 处,都是中括号,表示什么意思呢?就是说,这里的参数可有可无,可写可不写,我们来试试。
看到没有,也有一个闪烁的光标,说明服务启动了,官方文档,诚不欺我。
笔者经常看正版的官方文档,因为什么呢?里面的信息及时、准确、详细。对于掌握一个技术的细节,非常有用。
那么既然成功启动了 Web 服务,还说什么呢,访问一下呗。哎,不出意外地,看上图标记处,浏览器一直在加载中,等了很久都没有内容。
所以呢,光是创建一个 Web 服务,不提供任何参数,也是没有用武之地的。
那么我们再往回看,(1) 处的 options 和 (2) 处的 requestListener 分别表示什么呢?
你可以这么理解,如果把 Web 服务比做一个 "机器人",那么 options 就用来描述它的身高,体重,颜色,最多能待机多久,最大能携带多少的重物,多久没回答你的问题算超时等等。
而 requestListener,则表示机器人接受到来自触觉,视觉,听觉的数据后,该如何处理进行反馈。所以你看,极简 Web 的例子中是不是当收到请求后,设置为不会产生乱码的编码,然后返回 "你好,世界!" 呢。
这就是请求和响应,也可以叫做一问一答。Web 服务就是建立在一问一答的基础上的。
浏览器不断地向 Web 服务发送问题:
1,我要一个 html 页面。
2,页面中有 js 脚本,我也要。
3,还有个 CSS 样式,我还要。
4,还有好几个图片,快给我。
服务器不断地向浏览器返回响应:
1,html 页面给你了。
2,js 也给你了。
3,css 收到了吧。
4,给给给,图片。
天下武功,唯快不破。浏览器和 Web 服务器之间一问一答的时间,只有几十毫秒。而且它们之间,一次性可以进行多个问答,所以才让我们看到了网页刷刷地一下就出来了,这就是我们每天上网冲浪的基础。
但是也有页面卡顿,白屏的时候,什么问题呢?网络慢呗,图片大呗,Web 服务器没返回呗,无外乎此。
那么继续回到文档的艺术,这个方法还没说完呢。
options 属性中,有这么一个参数,最大 Http 头消息大小,默认值是 16384 字节,也就是 16KB。让我们来干点坏事,把这个值设置为 1。
记得,重新启动服务,然后到浏览器访问。
咦,不返回 "你好,世界!" 了,而且在 (5) 处,有个 431 的 Http 错误码,这是什么意思呢?我们来看看官方解释:http 状态码
哎,对上了,请求内容首部太大啦。
什么是请求首部呢?我们简单说一下,更多细节呢,请到笔者的问答群交流,不然这本小册,得变成大大册。
浏览器中,跟着上图的圆圈点击,其中 (6) 处就是头部,就是一问一答中的 "问 ",(7) 处就是 Web 服务器的响应,就是一问一答中的 "答"。那个大的方框框住的,就是 maxHeaderSize 属性的管控范围了。这么多字摆在这,明显大于 1 个字节,服务器当然不会返回内容啦。
不信这个邪?我们改成 10 万看看。
这不就来了吗~记得重启 Web 服务啊,靓仔!
所以你能看到,每个属性,都有大大的作用,存在即有理,有时候你没有用到,不代表它没有作用。
同时呢,你发现一个问题没有:为什么没有提供 options,只有一个监听函数的时候,也能正常运行呢?按照官方文档规范,第一个参数不应该是对象,第二个才是监听函数吗?所以,就算没有 options,第一个参数是不是设置为空对象才合理呢?
同学,我知道你问题很多,这个问题问得好。我知道你很急,但是请你别急。实现很简单,判断 createServer 的第一个参数,如果是函数,那就把 options 设置一个默认值就行了。
但是的但是,正如笔者第一章所说,我不是这个领域的专家,我只是一个编程界的老师傅。我不懂原理,不懂底层,真实的 createServer 实现我不清楚,但是要我判断一个坟墓里是不是死人,我还是能猜得八九不离十的。
有时候真相有那么重要吗?你开车一定要研究清楚发动机原理吗?没必要的对不对,量力而为嘛。笔者早早地就想清楚了这个问题,对自己也非常了解,不是搞钻研的料,已经多年没有深入地研究技术了。但是,在如何把自己熟悉的技术和知识,说清楚,讲明白这个问题上,我算得上是半个专家了。
什么是编程思维?能理解一二了吗?这就是笔者自学多年的经验,心得。
说得也不少了,我们最后通过看官方文档的艺术,来做一个实践:当 Web 服务启动后,打印一串字符,"服务已启动,监听端口为:8000"。
简单,完事。
问题倒不大,但是呢,不太正规。
我们继续看官方文档,createServer 执行后,返回了一个什么呢?是一个 Server 实例。
点击此处,我们去一探究竟,原来是一个 Server 类。我们的代码怎么写的?const server = createServer()。是不是把 Server 类实例化后赋值给了 server,那么这个 server 就具备了所有 Server 这个类的属性和方法。
文档往回拉,拉到开头处,找到 Server 类,在这里我们可以一览全貌,所有的属性和方法,尽收眼底,这就是我们能用上 server.listen(8000) 的原因,其实你用 const app = createServer(),然后 app.listen(80000) 也是一样的。
点击 server.listen() 后,来到上图,只有短短的一行字,以上就是:listen 方法跟 net 模块的 Server 方法的 listen 用法一样。看到没有,不光前端有什么组件复用,函数复用啊,人家文档也有,不然费那老劲写重复的内容,那不得烦死人啊。继续,点击圈住部分。
发现了新天地,用《桃花源记》来说,那就是:复行数十步,豁然开朗。
没想到一个小小的 listen 函数,这么多戏。咳咳,这么多写法。
图中呢,有第一个写法的示例,监听了 error 事件,那么除了 error 事件,还有哪些呢?有没有一个事件可以用来监听 Web 服务器已经启动了呢?我们继续往回拉,找到 listen 处。
error 事件看到了,紧邻其后,有一个 listening 事件,点击它。
监听端口成功后触发 listening 事件,那么我们照 error 猫画 listening 虎。
至此,艺术已成。
之后的课程中,不再分享如何看官方文档了,大家举一反三即可。
笔者自学的过程中,查阅官方文档的次数是最多的,正如前面所说,它及时,准确,详细。
当你掌握了看官方文档的艺术,很多问题都会迎刃而解。
而且,例子只要讲一个。
低级的教学,是填鸭式,重复地讲,没有思维方式。
高级的教学,是启发式,揉碎一个,其他的自己悟。