[Node入门] => 读书笔记(一)

来源:互联网 发布:淘宝出售假冒商品投诉 编辑:程序博客网 时间:2024/06/04 18:37

学习内容

  1. Node入门

学习笔记

1. 一个基础的HTTP服务器

[Node入门] 主文件叫做index.js或多或少是个标准格式,把服务器模块放进叫server.js的文件

// 使用require指令载入http模块const http = require('http');// 创建主机名和端口const hostname = '127.0.0.1';const port = 1337;// 创建服务器方法http.createServer()http.createServer((req, res) => {    // 发送http请求头,http状态码200,内容类型    res.writeHead(200, { 'Content-Type': 'text/plain' });     // 发送相应数据'Hello World'    res.end('Hello World\n');}).listen(port, hostname, () => {    // 终端listen端口,主机    console.log(`Server running at http://${hostname}:${port}/`);});

方法:http.createServer([requestListener])
说明:返回一个http.Server的新实例
来源:https://nodejs.org/dist/latest-v5.x/docs/api/http.html

注:’Hello World’ 样例来自NodeJs官网(https://nodejs.org/en/about/),使用了ES6语法。

2. 基于事件驱动的回调

2.1 阻塞、非阻塞、同步、异步

说明阻塞,非阻塞,异步,同步的一个来自网络的例子,作者不明:

老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。

所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

2.2 回调

[Node入门] 我们给某个方法传递了一个函数,这个方法在有相应事件发生时调用这个函数来进行回调 。

个人理解:
1. 老张 => 服务器, 水壶 => 用户请求。我们不知道水壶什么时候烧开水,亦即服务器不知道用户请求什么时候到来。
2. 假如使用响水壶,响水壶响了,亦即所谓“有相应事件发生时”
3. Node不像PHP,每多一个水壶就需要多一个老张来照看,100个请求需要100个进程;对于Node,一个老张照顾所有的响水壶,100个请求一个进程管理,因为这个过程是异步的,非阻塞的。

2.3 实例

书中,用这样一个类似例子,来解释了基于事件驱动的回调

const http = require('http');const hostname = '127.0.0.1';const port = 1337;http.createServer((req, res) => {    // 每一次请求,服务器刷新一段文本    console.log('Request received.');    res.writeHead(200, { 'Content-Type': 'text/plain' });     res.end('Hello World\n');}).listen(port, hostname, () => {    console.log(`Server running at http://${hostname}:${port}/`);});

3. 封装服务器模块

创建一个server.js如下:

const http = require('http');const hostname = '127.0.0.1';const port = 1337;function start() {    http.createServer((req, res) => {        console.log('Request received.');        res.writeHead(200, { 'Content-Type': 'text/plain' });        res.end('Hello World\n');    }).listen(port, hostname, () => {        console.log(`Server running at http://${hostname}:${port}/`);    });}// 导出函数exports.start = start;

通过创建index.js调用上述封装好的服务器模块,如下

// 读取服务器模块var server = require('./server.js');// 启动服务器server.start();

4. 路由

4.1 准备工作:获取请求的URL路径

例如:一个URL 对象'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
其中:pathname是'/p/a/t/h',search是'?query=string',path则是'/p/a/t/h?query=string'等等,具体可从官方API中查询。
来源:https://nodejs.org/dist/latest-v5.x/docs/api/url.html

4.2 使用依赖注入,添加路由模块

创建一个router.js路由模块

// 简单的输出下请求路径信息function route (pathname) {    console.log(`About to route a request for ${pathname}`);}exports.route = route;

更改server.js实现:

const http = require('http');// 载入url模块const url = require('url');const hostname = '127.0.0.1';const port = 1337;function start(route) {    http.createServer((req, res) => {        // 获取请求中的url路径        var pathname = url.parse(req.url).pathname;        console.log(`Request for ${pathname} received.`);        // 添加路由功能        route(pathname);        res.writeHead(200, { 'Content-Type': 'text/plain' });        res.end('Hello World\n');    }).listen(port, hostname, () => {        console.log(`Server running at http://${hostname}:${port}/`);    });}exports.start = start;

扩展index.js

var server = require('./server.js');var router = require('./router.js');server.start(router.route);

至此,一个简单的包含路由模块,路由模块的hello world级别的应用构建完毕。

0 0
原创粉丝点击