《Node.js高级编程》之Node 核心API基础
Node 核心API基础
- 第三章 加载模块
- 第四章 应用缓冲区
- 第五章 事件发射器模式简化事件绑定
- 第六章 使用定时器制定函数执行计划
第三章 加载模块
本章提要
- 加载模块
- 创建模块
- 使用node_modules文件夹
问题:
- 全局名称空间,共享
- 安全性问题、冲突、难以跟踪与解决。
Node解决
- 使用了CommonJS模块标准。
- 划分模块,根本没有全局作用域
3.1 理解Node如何加载模块
文件路径 + 名称
核心模块会预先加载
NPM安装模块
var module = require('module_name');
该对象表示模块对外暴露的 JavaScript API
它可以是一个函数,也可以是一个具有若干属性的对象,
属性可能是函数、数组,或者是其他类型。
3.2 导出模块
CommonJS模块系统
文件共享对象,函数.
模块和文件一一对应。
function Circle(x,y,r){
function r_squared(){
return Math.pow(r,2);
}
function area(){
return Math.PI * r_squared();
}
return {
area : area
}
}
module.exports = Circle;
module.exports
- 模块向需要它的脚本所导出的对象,可以是任意对象。
模块代码
function printA(){
console.log('A');
}
function printB(){
console.log('B');
}
function printC(){
console.log('C');
}
module.exports.printA = printA;
module.exports.printB = printB;
module.exports.pi = Math.PI;
引用模块
var myModule2 = require('./myModule2');
myModule2.printA();
myModule2.printB();
console.log(myModule2.pi);
3.3 加载模块
require函数不会改变全局名称空间的状态,Node种根本没有全局名称空间的概念。
3.3.1 加载核心模块
核心模块,二进制形式发布的模块。
只能通过模块名,而不能通过文件路径。
require(fs)
3.3.2 加载文件模块
提供绝对路径 或相对路径
从文件系统加载非核心模块
var myModule = require ('/home/carvendy/my_modules/my');
可以省略.js的扩展名
3.3.3 加载文件夹模块
var myModule = require('./myModuleDir');
查找包定义,package.json
包不存在就会找 index.js
3.3.4 从node_modules 文件夹加载
如果一个模块既不是相对路径,也不是核心模块,
那么就会尝试在当前目录下的 node_modules文件中查找。
var myModule = require('myModule.js');
当前目录没有myModule.js,就会往上一级父目录查找,持续到达根目录。
推荐还是让NPM来管理
3.3.4 缓存模块
模块在首次加载时,会被缓存起来,这意味着能被解析为相同的文件名。
console.log('module my_module initializing...');
module.exports = function (){
console.log('Hi!');
}
console.log('my_module initialized.');
然后加载
var myModule = require('./my_module');
输出
module my_module initializing...
module my_module initialized.
加载两次效果一样
模块在初始化,可能会有副作用
总结
- CommonJS模块系统取代,js默认全局名称空间
- 避免是安全性问题和错误。
- 使用require()加载模块
- 还可以编写 JavaSript导出的模块API
第四章 应用缓冲区处理、编码和解码二进制数据
#### 本章提要
- 理解Node 中为何需要缓冲区
- 用字符串创建缓冲区
- 将缓冲区转换成字符串
- 在缓冲区中处理数据
- 切分和复制缓冲区
问题
- js 善于处理字符串,但是它是被设计处理HTML,不擅长处理二进制数据。
- js没有字节类型,没有结构化类型,甚至没有字节数组
- 只有数值类型和字符串
Node 解决
- 处理HTTP文本协议
- 数据库通信、图像操作。
- 前期,使用字符串处理二进制,性能底下。
- 于是,引入了二进制缓冲区。(字节为计量单位)
补充
Buffer类的另一特别之处是数据占用的内存并不是分配JavaScript VM内存堆,这些对象不会被垃圾收集算法处理。
它会占据一个不会被修改的永久内存地址,这避免了因缓冲区内容的内存复制所造成的CPU浪费。
4.1 创建缓冲区
var buf = new Buffer('Hello World');//使用utf-8
var buf = new Buffer('8b76fdes713ce','base64');
编码
- ascii, ASCII字符集
- utf8, UTF-8
- base64,Base64个可打印的ASCII字符
如果缓冲区没有具体内容初始化,那么可以指定容量大小创建,备用
var buf = new Buffer(1024);
4.2 在缓冲区中获取和设置数据
查看某个字节
var buf = new Buffer('my buffer content');
console.log(buf[10]);//-->99 (随机值)
注意
- 设置一个大于255的数,将会用256对该数取模,赋值。
- 设置256,实际上被赋值为0
- 设置为100.7的小数,只会存储100
- 如果尝试给超出缓冲区边界的位置赋值,那么将会失败告终。
var buf = new Buffer(100);
console.log(buf.length);
4.3 切分缓冲区
对于已经创建的缓冲区,也许需要提取一部分。
var buffer = new Buffer('this is the content of my buffer');
var smallerBuffer = buffer.slice(8,9);
console.log(smallerBuffer.toString());
注意
切缓冲区,并没有分配新的内存。只不过引用父缓冲区的起始和结束位置。
修改父,删除父,可能会有错误,或内存泄漏。
4.4 赋值缓冲区
var buffer = new Buffer('this is the content of my buffer');
var smallerBuffer = buffer.slice(8,19);
console.log(smallerBuffer.toString());
var buf1 = new Buffer('this is the content of my buffer');
var buf2 = new Buffer(11);
var targetStart = 0;
var sourceStart = 8;
var sourceEnd = 19;
buf1.copy(buf2, targetStart , sourceStart , sourceEnd);
console.log(buf2.toString());
** 4.5 缓冲区解码**
var buf = new Buffer('this is the content of my buffer');
var str = buf.toString('base64');
打印
bXkgc3RyaW5n
第五章 使用事件发射器模式简化事件绑定
#### 本章提要:
- 事件发射器模式简介
- 绑定和解绑事件监听器
- 创建自定义的事件发射器
发射事件
类似于发布/订阅模式。
5.1 理解标准回调模式
异步编程不使用函数返回值代表结束,而使用后继传递。
每个函数执行完毕后都会调用一个回调函数。
var fs = require('fs');
fs.readFile('/etc/passwd',function(err,fileContent){
if(err){
throw err;
}
console.info('file content',fileContent.toString());
});
5.2 理解事件发射器模式
缺点
如果在函数执行过程中发生了很多事件,或者事件反复多次出现。
这样工作就不太好了。
事件发射器
看月发射事件的兑现,而事件监听器则是绑定到事件发射器上的代码,
负责监听特定类型的事件
var req = http.request(options,function(response){
response.on("data",function(data){
console.log("some data",data);
});
response.on("end",function(){
console.log("response ended");
});
});
PS
- 当需要在请求操作完成智慧重新获取控制权看月使用CPS模式
- 当事件可以发生多次时,就使用事件发射器模式
5.3 理解事件类型
事件类型
按照一般约定,事件类型都是由不包含开个的小写单词组成的。
无法通过编程判断发射了哪些类型的事件,API没有提供内省机制。
error事件
如果程序员选择不监听"error"事件,当事件发生是,事件发射器注意到它,并抛出未捕获异常。
var em = new (require('events').EventEmitter)();
em.emit('event1');//没有的事件
em.emit('error', new Error('My mistake'));// error马上打印堆栈
5.4 应用事件发生器API
方法
- .addListener 和.on —— 添加事件监听
- .once ——指定,并只邦定一个近被调用一次
- .removeEventListener ——删除
- .removeAllEventListener ——删除所有绑定的事件
5.4.1 使用.addListener或.on 绑回调函数
function receiveData(data){
console.info("got data from server");
}
readStream.addListener("data",receiveData);
分析
当有可用数据块时,文件可读流就会发射“data”事件
可以使用on代替:
readStream.on("data",receiveData);
PS:
data事件可能会传递数据缓冲区,error事件可能会传递一个错误对象,而流“end”事件则不向事件监听器传递任何参数。
5.4.2 绑定多个事件监听器
readStream.on("data",function(data){
console.log('I have data');
});
readStream.on("data",function(data){
console.log('I have data 2');
});
PS:
- 有注册顺序
- 监听器没有执行,可能是前面还有一个监听器
- 异常,可能会永远不会被执行。
- 第一个事件抛错误了,第二个监听器就不会执行。
5.4.3 .removeListener 删除
5.4.4. .once() 最多执行一次
var event = require('events').EventEmitter;
EventEmitter.prototype.once = function (type,callbak){
var that = this;
this.on(type,function listener(){
that.removeListener(type,listener);
callback.apply(that,arguments);//参数原封不动传递,再调回调函数
});
}
.removeAllListeners
5.5 创建事件发射器
5.5.1 从Node事件发射器继承
var util = require('util');
var events = require('events').EventEmitter;
var MyClass = function(){
//原型链
util.inherits(MyClass, EventEmitter);
}
发射事件
MyClass.prototype.someMethod = function (){
this.emit("custom event","argument 1","argument 2");
}
// 触发
var myClazz = new MyClass();
myClazz.on('custom event',function(str1,str2){
console.log("one:%s,two:%s",str1,str2);
});
myClazz.someMethod();
第六章 定时器指定函数执行计划
#### 本章提要
- 推迟函数的执行
- 取消执行计划
- 指定函数的周期行执行计划
- 将函数执行推迟到下一轮事件循环
Node全面实现一组函数,它们被用来再服务端辅助不通进程进行后期限或者推迟执行。
6.1 使用 setTimeout推迟
var timeout_ms = 2000;
var timeout = setTimeout(functino({
console.log('do sime');
}),timeout_ms);
clearTimeout(timeout);//取消函数计划
6.2 指定和取消函数的重复执行计划
var period = 1000;
setInterval(function(){
console.log("tick");
},period);
6.4 使用process.nextTick将函数执行推迟到下一个事件循环
有时候不需要立刻执行。
事件循环在一个处理事件队列的循环运行,事件循环每执行一次就被称为一个"tick"
process.nextTick 比激活超时队列块。
process.nextTick(function(){
my_expensive_conmputation_function();
});
6.5 阻塞队列事件循环
单线程事件循环。
运行时调用相关回调函数来处理队列的下个事件。
特殊情况,如果某个回调占用事件长,整个服务就会非常缓慢。
[阻塞]
process.nextTick(function nextTick1(){
var a = 0;
while(true){
a++;
}
});
process.nextTick(function nextTick2(){
console.log("2.....");
});
setTimeout(function timeout(){
console.log(1);
},1000);
6.6 推出事件循环
释放事件
6.7 使用 setTimeout 代替setInteval 前置函数串行
var inteval = 1000;
setInterval(function(){
my_async_function(function(){
console.log('finished...!');
});
});
《Node.js高级编程》之Node 核心API基础的更多相关文章
- Node.js高级编程读书笔记Outline
Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...
- 《Node.js 高级编程》简介与第二章笔记
<Node.js 高级编程> 作者简介 Pedro Teixerra 高产,开源项目程序员 Node 社区活跃成员,Node公司的创始人之一. 10岁开始编程,Visual Basic.C ...
- Node.js高级编程读书笔记 - 1 基本概念
Outline 1 概述和安装 1.1 安装Node 1.2 Node简介 2 Node核心API基础 2.1 加载模块 2.2 应用缓冲区处理.编码和解码二进制数据 2.3 使用时间发射器模式简化事 ...
- Node.js高级编程读书笔记 - 6 应用程序构建和调试 - Never
Explanation 现阶段console.log(...),util.inspect(...), JSON.stringify(...)在控制台输出已经够用了[2015/07/19]. 单元测试隶 ...
- Node.js高级编程读书笔记 - 5 数据库 - Never
Outline 6 连接数据库 6.1 使用node-mysql连接MySQL数据库 6.2 使用Nano连接CouchDB数据库 6.3 使用Mongoose连接MongoDB数据库 6 连接数据库 ...
- Node.js高级编程读书笔记 - 2 文件和进程处理
Outline 3 文件.进程.流和网络 3.1 查询和读写文件 3.2 创建和控制外部进程 3.3 读写数据流 3 文件.进程.流和网络 3.1 查询和读写文件 path 从Node 0.8起,pa ...
- Node.js高级编程读书笔记 - 4 构建Web应用程序
Outline 5 构建Web应用程序 5.1 构建和使用HTTP中间件 5.2 用Express.js创建Web应用程序 5.3 使用Socket.IO创建通用的实时Web应用程序 5 构建Web应 ...
- Node.js高级编程读书笔记 - 3 网络编程
Outline 3.4 构建TCP服务器 3.5 构建HTTP服务器 3.6 构建TCP客户端 3.7 创建HTTP请求 3.8 使用UDP 3.9 用TLS/SSL保证服务器的安全性 3.10 用H ...
- 深入理解node.js异步编程:基础篇
###[本文是基础内容,大神请绕道,才疏学浅,难免纰漏,请各位轻喷] ##1. 概述 目前开源社区最火热的技术当属Node.js莫属了,作为使用Javascript为主要开发语言的服务器端编程技术和平 ...
随机推荐
- model 字段参数 choice
class Banner(NewsBase): ''' 轮播图 ''' PRI_CHOICES = [ # 优先级的限制选择范围 (1,'第一级'), (2,'第二级'), (3,'第三级'), (4 ...
- WPF 初识
1.WPF 与Winform比较 1.1.WPF所有的操作都不依赖于GDI和GDI+,而是间接依赖于强大的Direct3D,这就意味着通过WPF可以做出以前WinFrom无法想象的视觉效果,包括3D效 ...
- easyui的datagrid改变整行颜色
easyui的datagrid改变单元格颜色方法1:https://www.cnblogs.com/raitorei/p/10395233.html easyui的datagrid改变单元格颜色方法2 ...
- 关于@JsonIgnore的理解
首先:@JsonIgnore是一个能够在后端发送给前端数据的时候对后端发送出的json字符串能够发挥作用的一个注解 如果比如user表,你在password这个属性上添加@JsonIgnore,就会s ...
- 对象属性拷贝工具类大全==>Bean的属性拷贝从此不用愁
大家在做java开发时,肯定会遇到api层参数对象传递给服务层,或者把service层的对象传递给dao层,他们之间又不是同一个类型对象,但字段又是一样,如果还是用普通的get.set方式来处理话,比 ...
- js如何实现重载
所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!但是我们知道js中是没有重载的,因为后定义的函数会覆盖前面的同名函数,但 ...
- 内嵌圆角CSS实现
前言 开发项目时,经常会遇到如上图左上角和右上角这种内嵌的圆角效果,在以前css3还没有普及时不用说一张图片搞定,但是到现在我们完全可以用css去实现. 实现 第一步:思路 仔细观察这个小缺角,它其实 ...
- DNN原理探究系列之目录与序章篇
序言: 神经网络结构,作为最成功的机器学习模型之一,其工作原理一直被埋藏得比较深,其解释性以至于被称为黑盒. 自己对于DNN的理解也只能算刚踏入了门槛,对于人脑的原理与DNN原理之间的互通性,一直是非 ...
- js电子表
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- H5新特性——--第三方绘图工具库 echarts(canvas)---SVG绘图
今天学习的内容 3.1:h5新特性---第三方绘图工具库 echarts(canvas) 百度 echarts;d3;two.js;.... 3.2:h5新特性---SVG绘图 3.2:h5新特性-- ...