上回我们说到啊,创建了一个极简的Web服务,监听了端口,设置了正确的编码,成功地在浏览器看到了返回的内容“你好,世界! ”。
那么本章节呢,我们通过一个简单的例子来分析,如何有效地查看官方文档。
首先,要知道官方文档在哪里,Node.js的官网地址是 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 虎。
至此,艺术已成。
之后的课程中,不再分享如何看官方文档了,大家举一反三即可。
笔者自学的过程中,查阅官方文档的次数是最多的,正如前面所说,它及时,准确,详细。
当你掌握了看官方文档的艺术,很多问题都会迎刃而解。
而且,例子只要讲一个。
低级的教学,是填鸭式,重复地讲,没有思维方式。
高级的教学,是启发式,揉碎一个,其他的自己悟。