【第三章—快速入门】《node.js开发指南》读书笔记

本文介绍Node.js的基础知识,包括如何建立HTTP服务器,理解异步式I/O与事件式编程,以及模块和包的概念。详细解释了阻塞与非阻塞的区别,以及Node.js如何通过单线程和事件循环提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第三章 Node.js快速入门

 

3.1.3 建立HTTP服务器

var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");

 

3.2 异步式I/O与事件式编程

node的特点是异步编程式I/O(非阻塞),通过事件和回调来组织。

 

3.2.1 阻塞和线程

阻塞(同步式I/O):遇到硬盘读写或网络通讯(即I/O操作)停止线程的cpu控制权,让给其他的线程。等待I/O操作结束恢复cpu控制权,之后继续运行。

非阻塞(异步式I/O):遇到I/O操作发送给操作系统,继续运行下一条语句。当完成后以事件形式通知回去。线程必须有事件循环,不断检查没有处理的事件,依次处理。

阻塞只能一次处理一项任务。提高吞吐量只能通过多线程。非阻塞单线程即可胜任,他核心利用率会保持100%。

阻塞模式下多线程可以让 CPU 资源不被阻塞中的线程浪费。

而在非阻塞模式下,线程不会被 I/O 阻塞,永远在利用 CPU。多线程带来的好处仅仅是在多核 CPU 的情况下利用更多的核,而Node.js的单线程也能带来同样的好处。

单线程的好处:既然阻塞和非阻塞效果相同,那么为什么非要选择非阻塞+单线程呢?

因为操作系统创建线程是昂贵的,需要分配内存、列入调度,同时在线程切换的时候还要执行内存换页, CPU 的缓存被
清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。 而单线程根本没这些烦恼。大大节约性能。

总结:如果一个工作的I/O操作远大于计算操作,那么非阻塞+单线程性能好很多。而web服务都是I/O操作很多的。

 

3.2.2 回调函数

使用回调函数实现异步。

var fs = require('fs');

//异步方式
fs.readFile('test.html','utf-8',(err,data)=>{
    if(err){
        console.log(err);
    }else{
        console.log(data);
    }
})

//同步方式
let data = fs.readFileSync('test.html','utf-8');
console.log(data);

 

3.2.3 事件

node.js所有异步I/O操作都会在完成时发送到事件队列,前面的fs.readFile和http.createServer都是通过eventEmitter实现的。

let Events = require('events');
let event = new Events.EventEmitter();

event.on('e',function(){
    console.log('a');
})

setTimeout(() => {
    event.emit('e');
}, 1000);

 

3.3 模块和包

模块(module)和包(package)是node.js的最重要的支柱。它用于拆分,封装,组合。

node.js模块基本遵从CommonJS标准。

 

3.3.1什么是模块?

模块是node.js程序基本组成部分,他可能是js代码,json或者编译的c++扩展。

 

3.3.2 创建模块

1.创建模块

使用exports公开接口,使用require获取。

exports只是module.exports的引用,如果你想要使用exports导出模块,千万不能给它赋值!

//m.js文件
var value = 42;

function sayHello() {
    console.log(value);
}

function setValue(v) {
    value = v;
}

exports.sayHello = sayHello;
exports.setValue = setValue;


//index.js
const m = request('./m');
m.sayHello(); //输出42

2.单次加载

request不会重复加载模块,无论调用多少次request加载的都是一个模块。

//index.js
var m1 = require('./m');
var m2 = require('./m');

m1.setValue(1);
m2.setValue(2);
m1.sayHello(); //输出2

 

 

由于书中的node.js版本太旧,3.34创建包和3.4调试已经不再适合现在的版本,所以不做记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值