nodeJS 入门实战
更新日期:
本篇博客是《Node入门》的读后笔记。
读后感:
我只想说:这哥们,我太爱了。最后成型的代码,有4个文件:功能简单,但是里面从无到有、从不合理再改进到合理的感觉实在太踏实了。不杂七杂八地引入其他不相干的概念,让整篇博客简洁、有序而又完整。总之,读着读着崇拜之心肆起,导致很有一种想娶Ta的冲动。
读书笔记:
实现功能:
1.请求服务器,得到一个可上传图片的表单
2.上传图片,提交表单
3.在页面上显示图片
一共4个文件,分别是:
1.index.js:主文件,server、router、handle 的粘合剂 【一件事:主人】
2.server.js:服务器,解析url 并把 handle request response 传给 router 【两件事:解析路径、传参】
3.router.js:路由,只路由,把 request response 传给相应的 handle【两件事:认识的传参,不认识的就404】
4.requestHandlers.js:请求处理器,好吧,这货才是真正底层的干实事的人儿 【一件事:干活】
从上面可以看出:各种参数接龙呀
1.请求-响应的关联数组:从 index -> server -> router
2.路由 router:从 index -> server
3.处理器 handle:从 index -> server -> router
4.request 和 response:从 server -> router -> handle
想知道为什么要写这么复杂扭曲麻烦的传参过程吗?怀着你满满的好奇心去读读原博吧,看看我老公怎么滴娓娓道来。此处主要写笔记的,就不大篇幅复制粘贴了。下面分别看看这4个文件,并浅聊下自己的疑惑、涨的姿势、认可、崇拜、以及疑惑。
index.js
|
|
- 对象 handle:把 url 对应到真正的请求处理函数
如此书写干净整洁,当成参数被传递到 server 端更灵活。而不是把对应关系硬编码到 server 端,还记得在学校实验室时写的一长串 switch-case 吗?还记得当时加一个新页面,就要从页面、controler、后端类走一遍整个流程吗?还记得当时熟悉的 ctrl+c、ctrl+v、再修改文本时流畅的体力劳动吗? - 把 handle 和 router 一起传到 server
这种结构让 server、router 更通用了。倘若要换个后台处理器,则只需要重新定义 handle 对象即可-并当成参数传过去即可。而且结构和层级都比较清晰,各部分耦合也低,方便维护。
其他:
- HTTP 服务器要提供 web 页面:路由-不同url不同的响应,把请求传到对应的‘请求处理程序’那里,请求处理程序-处理请求
- ?? 在主js的文件里,暴露了router和handle,总觉得怪怪的。对于我这种纯浏览器端js的纯FEer,还真是没拐过来弯儿来…【那个,醒醒,此处是“后端JavaScript”的地盘。另外,此时你console.log()下,那就直接打印到神秘的黑屏上了哦~~日志】
- ?? 感觉把关联数组 handle 写在 router 里也可以啊….【但是,貌似 router 就不通用了-和业务本身挂钩】嗯,所以此处是把 server 和 router都“提”出来了,只有 handle+requestHandlers 和具体业务相关。这么一想,确实八错。
server.js
|
|
- 创建服务器时,为什么要搞个回调函数 function(request, response){} 呢?
因为 nodeJS 是事件驱动的,这是它原生的工作方式。而,用它来写网络应用是有意义的,因为 HTTP 请求到来的时候就是异步的,而我们的服务器是跑在一个单进程中的。一句话就是:nodeJS/JavaScript 事件驱动,当事件来了,就去执行传过来的回调。#事件驱动的异步服务器JS和它的回调#
Note:php是任何时候有请求来时,服务器(通常是 apache)就为请求新建一个进程,且从头到尾执行相应的php脚本 - 没有直接在 server 端 return response,而是把 response 通过 route 传递给 handle
原因:如果在 server 里静等 handle 返回结果,然后统一返回 response,那就会导致 当未来要处理比较耗时的操作时,我们的服务器就“挂”了,即服务器被阻塞了。
Note:因为 nodeJS 是单线程的,它通过事件轮询(event loop)来实现并行操作,所以我们要充分利用这一点-尽可能避免阻塞操作,多使用非阻塞操作。 - 把 request 通过 route 传递给 handle
原因:get啊、post啊、数据啊等,一切都由请求处理程序处理更合适。形式和数据辣么多样,是吧。
其他:
- 当访问网页时,服务器可能会输出两次”Request received”,那是因为大部分服务器会在你访问 http://localhost:8888/ 时尝试读取 http://localhost:8888/favicon.ico
- 它应当属于路由or服务器or一个模块自身的功能,确实值得探讨,这里暂定HTTP服务器的功能【特别喜欢人家的坦诚,把不确定的 不知道的都真诚的明明白白地说出来】
- 可以用 querystring 模块来解析 POST 请求体中的参数
- 其实说白了,处理文件上传“就是”处理POST数据
- 如何重启服务? ctrl+c 杀死进程的监听端口
router.js
|
|
- 路由:并不是真正有所行动的模块
在现在的实现下,路由过程会在路由模块中“结束”,并且路由模块并不是真正针对请求“采取行动”的模块,否则当我们的应用程序变得更为复杂时,将无法很好地扩展 - 函数式编程
其实是一种编程哲学,即直接传“动作”,而不是传“名词”。举例:我们传过去一个东西,别人可以这么用:“嗨那个叫路由的东西,能帮我把这个路由一下吗?”其实你不需要东西,你需要的是一个动作….即你不需要名词,而是需要动词。可以看看 《名词王国中的死刑》 来更好的理解函数式编程
requestHandlers.js
|
|
- 选择:是将 requestHandlers 模块硬编码到路由里来使用,还是再添加一点依赖注入?
虽然和其他模式一样,依赖注入不应该仅仅为使用而使用,但在现在这个情况下,使用依赖注入可以让路由和请求处理程序之间的耦合更加松散,也因此能让路由的重用性更高。这里,选择了“依赖注入”。
其他:
- 当是 POST 请求时,
(1)Node.js 会将 post 数据拆分成很多小的数据块 -> 触发特定事件(将小块数据传递给回调函数)
eg. data 事件,新的小数据块到达了;end 事件,所有的数据都已接收完毕
(2)我们要做的是:告诉Node.js当这些事件触发时,都回调哪些函数。
怎么告诉? 在 request 对象上注册监听器,request 对象是每次接收到 HTTP 请求时,都会把该对象传递给 onRequest 回调函数。
request.data(); request.end();
很爱博主的几个小点:
- 一条线很清晰:该扩展的扩展,该省略的省略;该详细的详细,该讲解的讲解,该不懂的人家也不装懂(其实更多的是站在读者的角度去进行个思维转换-让读者有代入感)….特别喜爱这样的人。读某些文章,简直就是一种享受。
- “我不想去解释 noun1 和 noun2 的具体含义,我们直接来看,当程序中加入了 noun1 的操作后会发生什么。”
这就是程序员自己的魅力啊,不需要单纯的讲解概念本身,而是实战理论相结合。帅气。 - 最直截了当的实现方式事实上并不是非常靠谱:看似有效,实则未必如此。我们先就这样去实现,然后再来看为什么这不是一种很好的实现方式。
看看看,循循善诱的方式啊,多温暖,多温柔,多有耐心。