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

学习内容

  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级别的应用构建完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值