Node基础知识笔记
Posted 过往将来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node基础知识笔记相关的知识,希望对你有一定的参考价值。
全文目录
Node.js简介
- Node.js就是运行在服务器端的javascript,Node.js是一个基于Chorme JavaScript运行时建立的一个平台。
- Node.js时一个事件驱动I/O服务器端JavaScript环境,性能很好
Node 应用简介
- 使用Node建立一个应用时,还同时实现了整个HTTP服务器,实际上,Web应用以及对应的Web服务器基本是一样的。
- Node.js应用的组成包含三部分:引入require模块,创建服务器,接收请求与相应请求
- 引入require模块:我们可以使用require指令来载入Node.js模块
- 创建服务器:服务器可以监听客服端的请求,类似与nginx等HTTP服务器。
- 接收请求与响应请求:服务器很容易创建,客户端可以使用浏览器或者终端发送HTTP请求,服务器接受请求后返回响应数据。
Node创建的hello world
- 创建一个server.js文件,输入以下内容
var http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\\n');
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
- 使用require指令来载入http模块,并将实例化的HTTP赋值给http
- 使用http.createServer()方法创建服务器,并使用listen方法绑定8888端口.函数通过request,response参数来接收和响应数据。
- 使用 node server.js 执行server.js文件,此时,在浏览器中访问http://127.0.0.1:8888/可以查看到hello world
npm知识点
npm 简介
npm
是随同node.js
一起安装的报管理工具,能解决node.js
代码部署上的很多问题。
npm的使用场景
- 使用
npm
可以从服务器端下载别人编写好的第三方包到本地使用 - 使用
npm
从服务器下载并安装别人编写的命令行程序到本地使用。 - 使用
npm
可以将自己编写的包或者命令行程序上传到npm
服务器供别人使用
npm 命令集合
- 使用
npm install
安装npm
。 npm -v
查看npm
是否安装成功。npm install npm -g
来升级npm
4.的版本。- 使用
npm
配置淘宝镜像:npm install -g --registry=https://registry.npm.taobao.org
. - 注意:不用使用
npm install -g cnpm --registry=https://registry.npm.taobao.org
这种方式配置淘宝镜像,因为cnpm
下载下来的第三方包的路径有时会很奇怪,会出现不可预知的错误! npm
的安装分为本地安装local
和全局安装global
,npm install express
本地安装express
,npm install express -g
全局安装express
.- 如果出现此错误:
npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
,解决办法为:$ npm config set proxy null
。 npm list -g
命令查看所有全局安装的模块!npm list grunt
查看某个模块的版本号.npm uninstall <Module Name>
卸载npm
模块,卸载后,你可以到/node_modules/
目录下查看包是否还存在,或者使用以下命令查看:npm ls
npm update <Module Name>
可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。。npm update <package> -g
可以把全局安装的对应命令行程序更新至最新版。npm search <Module Name>
搜索npm模块npm help <command>
可查看某条命令的详细帮助,例如npm help install
.npm cache clear
可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。npm init
创建一个模板生成package.json。让我们使用 npm 产生 package.json。
npm的具体使用
- 使用
npm
安装的模板语法:npm install <Module Name>
,比如使用npm
安装常用的Node
的web框架express
。 - 在安装好了之后,
express
包就放在了根目录下的node_modules
目录中,只需要通过var express = require('express');
的方式就可以引用该包,无需指定第三方包的路径。 npm install express -g
,全局安装express
包,不加-g
默认为本地安装。
npm 本地安装详解
- 将安装包放在
./node_modules
下,(运行npm
命令时所在的目录),如果没有node_modules
目录,会在当前执行npm
命令时生成node_modules
目录。 - 可以通过require()来引入本地安装的包。
npm 全局安装详解
- 全局安装在安装包放在
/uer/local
或者 你的node
安装目录中!!注意:node
的安装路径中!不要使用中文!!!不要使用中文!!!一定不要使用中文!!如果使用中文,在具体使用第三方包时会出现错误。 - 全局安装可以直接在cmd打开的命令行中使用、
npm 安装时异常的处理
- 使用
npm
安 装node_modules
总是提示报错:报错:npm resource busy or locked.....
。可以先删除以前安装的node_modules
使用npm cache clean
,然后再重新安装:npm install
.
第三方包知识点
第三方包简介
- package.json的使用说明:package.json 位于模块的目录下,用于定义包的属性。
- name-包名,
- version-包的版本号
- description-包的描述
- homepage-包的官网url
- author-包的作者姓名
- contributors - 包的其他贡献者姓名。
- dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
- repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
- main - main 字段指定了程序的主入口文件,require(‘moduleName’) 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
- .keywords - 关键字
Node.js 回调函数
- 回调是一种异步相当于一个函数,回调函书被调用在完成既定任务,
回调函数
Node.js
的回调函数:Node.js
异步编程的直接体现就是回调,异步编程依托于回调来实现,但是不能说使用了回调后程序就异步化了!回调函数再完成任务后就会被调用,Node使用了大量的回调函数,Node所有的API都支持回调函数。
2.例如:一边读取文件,一边执行其他命令,再文件读取完成后,将文件内容作为回调函数的参数返回,这样再执行代码时就没有阻塞或者等待文件的I/O操作。这样提高了Node.js的性能,可以处理大量的并发请求。- 回调函数一般作为函数的最后一个参数出现,
function foo1(name, age, callbackName){}
,function foo2(value,callback1,callbackName){}
阻塞代码测试
- 在根目录下,创建一个input.txt文件,内容为:百度网址:www.baidu.com
- 在
main.js
文件中,代码如下:
var fs = require('fs');在这里需要安装fs的包,如果不安装的话,会报错
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("程序执行结束");
在终端使用 node main.js。
终端打印如下信息:
百度网址:www.baidu.com
程序执行结束
- 阻塞测试案例:是在文件读取完成后才执行程序,
- 阻塞时按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数.我们就需要写在回调函数内.
非阻塞代码测试
- 在
main.js
文件中的代码如下:
var fs = require('fs');
fs.readFile('input.txt',function(err,data){
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序执行结束");
在终端使用 node main.js。
终端打印如下信息:
程序执行结束
百度网址:www.baidu.com
- 非阻塞测试案例:我们不需要等待文件读取完,这样就可以在读取文件的同时执行接下来的代码.从而提高程序的性能。
- 阻塞时按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数.我们就需要写在回调函数内.
Node.js事件循环
Node.js
是单线程应用,但它通过事件和回调的概念支持并发。Node.js
每个API都是异步的,作为一个单线程,node
使用异步函数调用来维护并发。Node
线程保持一个事件循环,每当任何一个任务完成后得到结果,node
就触发通知事件侦听函数来执行相应的事件。Node.js
单线程类似进入一个while(true)
的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
事件驱动程序
-
Node.js
使用事件驱动模型,每当web server
接收到请求,就把它关闭进行处理,然后再去服务下一个web请求,党这个请求完成之后,它被放回处理队列,当到达队列开头,这个结果就被返回给用户。 -
事件驱动模型非常高效,可扩展性很强,因为web server一直接受请求而不等待任何读写操作(也成为非阻塞式IO或者事件驱动IO)
-
在事件驱动模型中,会生成一个主循环来监听事件,每当检测到事件时触发回调函数。
-
事件驱动流程图如下所示
-
Node.js有多个内置事件,通过引入
events
模块,实例化EventEmitter
类来绑定和监听事件
var events = require('events');
var eventEmitter = new events.EventEmitter(); // 创建eventmitter对象
// 创建事件处理程序
var connectHandler = function connected(){
console.log('连接成功');
eventEmitter.emit('data_received');// 触发data_received 事件
}
eventEmitter.on('connection',connectHandler); // 绑定connection 事件处理程序
eventEmitter.on('data_received',function(){ // 使用匿名函数绑定 data_received 事件
console.log('数据接受成功');
})
eventEmitter.emit('connection');// 触发 connection 事件
console.log('程序执行完毕');
在终端执行 node main.js 输出结果:
连接成功
数据接受成功
程序执行完毕
Node应用程序工作流程
- 在
Node
应用程序中,执行异步操作的函数将回调函数作为最后一个参数,回调函数接收错误对象作为第一个参数。
var fs = require("fs");
fs.readFile("input.txt",function(err,data){
if(err){
console.log(err.stack);
return;
}
console.log(data.toString());
})
console.log("程序执行完毕")
readFile()
是异步函数用于读取文件,如果读取文件过程中发生错误,错误err
对象就会输出错误信息。- 如果没有发生错误就会跳过
err
对象的输出,文件内容就会通过回调函数输出、
进程和线程的概念
- 进程是指系统中正在运行的一个应用程序,程序一旦运行就是进程,进程是系统进行资源分配的独立实体,每个进行拥有独立的地址空间。
- 一个进程之间可以拥有多个线程,每个线程使用其所属进程的栈空间
- 线程是进程的一个实体,是进程的一条执行路径,线程是CPU独立运行和独立调度的基本单位。
Node EventEmitter 事件发射器详解
Node
所有的异步I/O
操作在完成时都会发送一个事件到事件队列- Node里面很多对象都会分发事件,一个
net.Server
对象会在每次有新连接时触发一个事件, - 一个
fs.readStream
对象会在文件被打开的时候触发一个事件。 所有这些产生事件的对象都是events.EventEmitter
的实例。
Node EventEmitter 类`
events
模块只提供了一个对象:events.EventEmitter
。EventEmitter
的核心就是事件触发与事件监听器功能的封装。EventEmitter
对象如果在实例化时发生错误,会触发error
事件,当添加新的监听器时,newListener
事件会被触发,当监听器被移除时,removeListener
事件被触发。
实例一:简单介绍EventEmitter的用法
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
console.log('some_event 事件触发');
});
setTimeout(function() {
event.emit('some_event');
}, 1000);
在1秒后,输出some_event 事件触发,这是因为event对象注册了事件some_event的一个监听器,然后通过setTimeout在1秒后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。
EventEmitter
的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。- 对于每个事件,
EventEmitter
支持 若干个事件监听器。当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
实例二:EventEmitter绑定事件和触发事件
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数 A', 'arg2 参数 B');
emitter 为事件 someEvent 注册了两个事件监听器,然后触发了 someEvent 事件。两个事件监听器回调函数被先后调用。 这就是EventEmitter最简单的用法。
EventEmitter 属性介绍:
-
addListener(event,listener)
为指定事件添加一个监听器到监听器数据的尾部 -
on(event,listener)
为指定事件注册一个监听器,接受一个字符串event
和一个回调函数server.on('connection', function (stream) { console.log('someone connected!'); });
-
once(event,listener)
为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器server.once('connection', function (stream) { console.log('Ah, we have our first user!'); });
-
removeListener(event, listener)
移除指定事件的某个监听器,监听器必须时该事件已经注册过的监听器removeListener(event,listener)
接受两个参数,第一个是事件名称,第二个是回调函数名称var callback = function(stream) { console.log('someone connected!'); }; server.on('connection', callback); server.removeListener('connection', callback);
-
removeAllListeners([event])
移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。 -
setMaxListeners(n)
默认情况下,EventEmitters
如果你添加的监听器超过 10 个就会输出警告信息。setMaxListeners
函数用于改变监听器的默认限制的数量。 -
listeners(event)
返回指定事件的监听器数组 -
emit(event,[arg1],[arg2],[...])
按照监听器的顺序执行每个监听器,如果事件有注册监听返回true
,否则返回false
EventEmitter 方法介绍:
events.emitter.listenerCount(eventName)
//推荐返回指定事件的监听器数量。
EventEmitter 事件介绍
-
newListener(event,listener)
在添加新监听器时被触发,event
是字符串,事件名称,listener
处理事件函数 -
removeListener(event,listener)
从指定监听器数组中删除一个监听器,此操作将会改变处于被删监听器之后的那些监听器的索引。
实例三:通过 connection(连接)事件演示了 EventEmitter 类的应用。
var events = require('events');
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
console.log('监听器 listener1 执行。');
}
// 监听器 #2
var listener2 = function listener2() {
console.log('监听器 listener2 执行。');
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener('connection', listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);
var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
// 处理 connection 事件
eventEmitter.emit('connection');
// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");
// 触发连接事件
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕。");
输出结果为:
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。
error事件介绍
EventEmitter
定义了一个特殊的事件error
,它包含了错误的语义,我们在遇到 异常的时候通常会触发error
事件。- 当
error
被触发时,EventEmitter
规定如果没有响 应的监听器,Node.js
会把它当作异常,退出程序并输出错误信息。 - 一般要为会触发
error
事件的对象设置监听器,避免遇到错误后整个程序崩溃。
继承 EventEmitter
- 我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
- 具有某个实体功能的对象实现事件符合语义, 事件的监听和发生应该是一个对象的方法。
- JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
Node Buffer(缓冲区)知识点
- JS语言本身只有字符串数据类型,没有二进制数据类型,但是在处理TCP流或者文件流的时候,必须用到二进制数据,因此在Node中定义了一个
Buffer
类,用来创建一个专门存放二进制数据的缓存区。
2.``Buffer类是Node的核心库,
Buffer为node带来了一种存储元素数据的方法,从而可以让Node处理二进制数据,每当Node中处理I/O操作中移动数据的时候,就可以使用
Buffer`类。 - 原始数据存储在
Buffer
类的实例中,一个Buffer
类相当于一个整数数组. - 使用 Buffer.from() 接口去创建Buffer对象。
Buffer与字符编码
- Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。
- 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。
const buf = Buffer.from('runoob', 'ascii');
// 输出 72756e6f6f62
console.log(buf.toString('hex'));
// 输出 cnVub29i
console.log(buf.toString('base64'));
Node支持的字符编码
- ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
- utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
- utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
- ucs2 - utf16le 的别名
- base64 - Base64 编码。
- latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
- binary - latin1 的别名。
- hex - 将每个字节编码为两个十六进制字符。
Buffer 提供了 API 来创建 Buffer 类:
Buffer.alloc(size[, fill[, encoding]]):
返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0Buffer.allocUnsafe(size):
返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据Buffer.from(array)
: 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)Buffer.from(arrayBuffer[, byteOffset[, length]])
: 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。Buffer.from(buffer):
复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例Buffer.from(string[, encoding])
: 返回一个被 string 的值初始化的新的 Buffer 实例
利用Buffer写入Node缓冲区
- 写入 Node 缓冲区的语法:
buf.write(string[, offset[, length]][, encoding])
. string
- 写入缓冲区的字符串。offset
- 缓冲区开始写入的索引值,默认为 0 。length
- 写入的字节数,默认为 buffer.length
5.encoding
- 使用的编码。默认为 ‘utf8’ 。- 如果
buf
没有足够的空间保存整个字符串,则只会写入string
的一部分。 只部分解码的字符不会被写入。 - 返回实际写入的大小。如果
buffer
空间不足, 则只会写入部分字符串。
实例一:简单的缓冲区演示
buf = Buffer.alloc(256);
len = buf.write("www.baidu.com");
console.log("写入字节数 : "+ len);
利用Buffer从缓冲区中读取数据
- 读取 Node 缓冲区数据的语法:
buf.toString([encoding[, start[, end]]])
encoding
- 使用的编码。默认为 ‘utf8’ 。
3.start
- 指定开始读取的索引位置,默认为 0。end
- 结束位置,默认为缓冲区的末尾。- 返回值为:解码缓冲区数据并使用指定的编码返回字符串。
实例一:从缓冲区中读取数据的演示
buf = Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97;
}
console.log( buf.toString('ascii')); // 输出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5)); //使用 'ascii' 编码, 并输出: abcde
console.log( buf.toString('utf8',0,5)); // 使用 'utf8' 编码, 并输出: abcde
console.log( buf.toString(undefined,0,5)); // 使用默认的 'utf8' 编码, 并输出: abcde
将 Buffer 转换为 JSON 对象
- 将
Node Buffer
转换为JSON
对象的函数语法格式:buf.toJSON()
- 当字符串化一个
Buffer
实例时,JSON.stringify()
会隐式地调用该toJSON()
。 - 返回值为
JSON
对象
实例一:将 Buffer 转换为 JSON 对象
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value) => {
return value && value.type === 'Buffer' ?
Buffer.from(value.data) :
value;
});
// 输出: <Buffer 01 02 03 04 05>
console.log(copy);
Buffer 缓冲区合并
- Node 缓冲区合并的语法:
Buffer.concat(list[, totalLength])
list
- 用于合并的Buffer
对象数组列表。totalLength
- 指定合并后Buffer
对象的总长度。- 返回一个多个成员合并的新
Buffer
对象。
实例一:简单的Buffer缓冲区合并
var buffer1 = Buffer.from(('百度'));
var buffer2 = Buffer.from(('www.baidu.com'));
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("buffer3 内容: " + buffer3.toString());
Buffer 缓冲区比较
- 缓冲区比较语法:
buf.compare(otherBuffer);
otherBuffer
- 与buf
对象比较的另外一个Buffer
对象。- 返回一个数字,表示
buf
在 `otherBuffer 之前,之后或相同。
实例一:Buffer缓冲区比较
var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABCD');
var result = buffer1.compare(buffer2);
if(result < 0) {
console.log(buffer1 + DOM探索之基础详解——学习笔记