node.js 基础

248 阅读8分钟
  • 版本:单数是非稳定版,双数是稳定版,推荐版本8以上
  • 定义:node.js是一个将多种技术结合起来的平台,可以让javaScript

能调用系统接口,开发后端应用。基于v8引擎的js运行环境。

  • 相关技术:v8引擎 、 libuv

C / C++实现的 c-ares , http-parser ,OpenSSL , zlib 等库

一、node.js技术架构(了解)

注: 1. steam写错了,应该是stream 2. node.js 框架 Express 、egg.js等

1. bindings

  • 原理:为了使js可以调用c++的库,binding提供了中间桥梁的功能

首先node.js 封装c++库 [ **.cpp文件 ],再将封装后的代码编译成 .node 文件

这样 js 代码就可以直接require这个.node文件。binding有很多种。

  • 定义:让 js 和 c / c++ 通信

2. libuv

  • 功能:可以用于 TCP、UDP、DNS 文件等的异步操作。

跨平台的异步I/O库。进行异步I/O操作。

3. V8

  • 功能:将js源代码变成本地代码并执行

维护调用栈,确保js函数的执行顺序

内存管理,为所有对象分配内存

垃圾回收,重复利用无用的内存

实现js的标准库

  • 注意:v8执行 js 是单线程的,可以开启两个线程分别执行js

v8本身是包含多个线程的,比如垃圾回收为单独线程

自带event loop但是node.js基于libuv 自己做了一个

4. Event loop

  • Event:事件
  • Loop:循环
  • Event Loop:操作系统可以出发事件,js可以处理事件

Event Loop 就是对事件处理顺序的管理

二、命令行相关

  • yarn init -y 创建一个 package.json 文件,初始化文件
  • node index 使用node 运行 index 文件

1、commander.js 库

简介 基础的 node.js 命令行界面 cli的相关库,支持链式操作

安装 : ****npm install commander 或者 yarn add commander

(1)option()方法
  • 作用:定义 commander 的选项 options
const program=require('commander') // 表示引用
program.option('-x,--xxx','what is  xxx')
program.option('-n, --name <items1> [items2]', 'name description', 'default value')
// 在输入 node -xxx 时 第一个参数是会执行的可选项,第二个参数是对可选项的描述
// 会有一个默认的-h  表示help 打出所有的option  
(2)command() 方法
  • 作用:添加子命令
x.command ('add <num> [otherDirs...]', 'install description', opts)
//尖括号为必填参数 表示执行add命令时 必填的选项
(3)alias()别名 description()描述 usage() 用法
.alias('r') //别名
  .usage('[options] <file ...>') // 用法
  .description('自定义') //描述
(4)action()方法
  • 作用:添加一个 command 回调函数
(5)version()方法
  • 作用: 为当前的program添加一个版本号,可以在npm发布新版本或者安装
const program=require('commander') // 表示引用
program.version('0.01')
(6)示例
const program =require('commander');

program.option('-x,-xxx','what the x')
program
  .command('add')
  .description('add a task')
  .action((...args)=>{
  	const word=args.slice(0,-1).join('')
    console.log(words);
	});


// process.argv 表示用户目前传了哪些参数的路径 例如node index.js 会显示 node和index.js的地址
program.parse(process.argv);

// 使用方式  node index -x add username;

2、inquirer.js 库

简介: 命令行可视化库

安装: yarn add inquirer

使用方式: inquirer.prompt(questions, answers) -> promise

(1)inquirer.js 库 相关操作

参考掘金: juejin.cn/post/702891… 作者: 支木

参考掘金: juejin.cn/post/696650… 作者: CookiePool

const inquirer = require('inquire')

const question = [
  {
    type: 'list', // 问题类型,默认是input,可以选input, number, confirm, list, rawlist, expand, checkbox, password, editor
    name: 'size', // 用户选择后的选项名称,可以和answer中的key一致
    message: '请选择一个选项', // 显示在命令行上消息
    /*---------------------------------------------------*/
    // choices是提供给用户的选项,接受一个数组或function,数组的index可以配合name使用
    // 数组接受对象{name,value:index.toString()}(value值应为字符串)
    choices: ['Larger', 'Medium', 'Smaller'],
    filter (val) {
      return val.toLowerCase()
    }
  }
]
//answer 的key相当于对应question里面的name属性
//answer 的value 对应的值取决于你的prompt问题的类型
inquirer.prompt(question).then(answer => {
  console.log(answer)
})
(2)question 可选 type
  • input 类型 ****这个类型允许用户进行输入操作
  • number 类型 ****仅允许用户输入数字,如果不是数字,则结果对应的是NaN
  • confirm 类型 ****给出单项选择,让用户选择Y/n
  • list 类型 ****列出一系列选项让用户选择
  • rawlist 类型 ****类似list类型,显示序号,会在选项最后预览当前选中的选项的序号
  • expand 类型 ****提供一个指定key值的value选项
  • checkbox 类型 ****多选
  • password 类型 ****这个可以定义用户输入为密码类型
  • editor 类型 调用电脑的编辑器(windows为记事本)来编辑对应的文本并输出

三、node.js文件模块 fs

  • 简介fs 模块 是Node.js 官方提供的用来操作文件的模块。

它提供了一系列的方法和属性,用来满足用户对文件的操作需求。所有api默认异步执行

    1. fs.readFile(path,[options],callback) 用来 读取 ****指定文件中的内容
    1. fs.writeFile(file,data,[options],callback) 用来向指定的文件中 写入 内容
  • 3.fs.open ****以指定方式打开文件
    1. ****fs.read ****以指定方式读文件
const fs = require('fs') // 导入fs模块
const homedir = require('os').homedir() // 获取home目录路径
// 获取用户自定义的home目录路径,比如window环境变量配置
const home = process.env.HOME || homedir 

// 1. 读取文件后, 回调函数会有两个参数,function(error,data)**promise**
fs.readFile(文件路径,[解码方式可省略],回调函数)

// 2. 写入文件后, 回调函数会有一个参数,function(error)
fs.writeFile(文件路径,写入的内容,[写入的格式默认utf-8],回调函数)

// 3. 要打开的文件路径和打开方式
fs.open(path, flags, mode, callback(err, fd))
fs.open('path',flags)
// 4. 
fs.read(fd, buffer, offset, length, position, [callback(err, bytesRead, buffer)])

flags 的可选值

  • r :以读取模式打开文件。
  • r+ :以读写模式打开文件。
  • w :以写入模式打开文件,如果文件不存在则创建。
  • w+ :以读写模式打开文件,如果文件不存在则创建。
  • a :以追加模式打开文件,如果文件不存在则创建。
  • a+ :以读取追加模式打开文件,如果文件不存在则创建

四、单元测试

  • 测试工具: jest
  • 安装方法: yarn add --dev jest****
  • 相关文件: FileName.test.js ****新建一个自定义的文件,需要以 ****.test.js ****结尾

参考: 掘金 ****juejin.cn/post/684490…

官网 : www.jestjs.cn/docs/gettin…

1、在package.json中加入如下代码

  • 配置完成后使用yarn test 可以运行 jest
{
  "scripts": {
    "test": "jest" // 配置 测试使用jest
  }
}

2、示例

使用 expecttoBe 检测两个值是否完全相等(toBe只能判断基础值)

// sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;

// sum.test.js
const sum = require('./sum');
//test函数生成一条测试,第一个参数是一个描述性的字符串,第二个参数是测试的函数
test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

//输出结果
PASS  ./sum.test.js
✓ adds 1 + 2 to equal 3 (5ms)
  • toEqual 判断引用类型
  • toBeNull 判断是否为null 同类的还有toBeUndefined``toBeDefined``toBeTruth``toBeFalsy
  • not.toBe 对toBe取反
  • toBeGreaterThan 判断数字相关的等等
  • toMatch 判断字符串是否匹配
  • toContain 判断数组是否包含某个元素
  • toHaveLength 判断数组长度
  • toThrow 判断错误是否符合预期

五、path模块 (路径)

node.js 核心模块之一,可以直接引用 const path = require ('path')

  • path.sep ****路径分割符 , window是 ****/ ****mac 和 linux 是 ****``
  • path.delimiter ****路径界定符,windows 是 ****mac 和 linux是 ****:
  • path.basename('路径','扩展名') ****返回路径的最后一部分,第二个参数可以过滤掉扩展名
  • path.dirname() 返回路径的目录部分
  • path.extname() 返回路径的扩展名部分
  • path.isAbsolute() 如果是绝对路径就返回true
  • path.join() 连接两个或多个路径
  • path.normalize() 当路径中包含. .. // 等相对的说明符时,尝试计算实际的路径
  • path .parse() 解析对象的路径,组成其的片段 :

root :根路径 dir : 从根路径开始的文件夹路径 base :文件名+扩展名 name :文件名 ext : 文件扩展名

require('path').parse('/users/test.txt')
{
  root: '/',
  dir: '/users',
  base: 'test.txt',
  ext: '.txt',
  name: 'test'
}
  • path.relative() 接受2个路径为参数,基于当前目录返回从第一个路径到第二个路径的相对路径
  • path.resolve() 接受一个参数相对路径,获得其绝对路径,若是两个参数,第一个参数会作为第二个参数的基准

六、HTTP模块

node.js 核心模块之一,可以直接引用 const path = require ('http')

  • http.METHDDS 所有支持的HTTP方法
  • http.STATUS_CODES 所有的HTTP状态码及其描述
  • http.createServer()
const server = http.createServer((request, response) => {
  //使用此回调处理每个单独的请求。
})
  • http.request() 发送http请求并创建 http.ClientRequest 类的实例
  • http.get() 发送http请求,方法为get ,并自动调用 req.end()
  • http.Agent
  • http.ClientRequest 当请求被调用时,创建对象,当响应被接收时,会响应来调用 response 事件,可以通过 response.read() 方法来读取
  • http.Server 当使用http.createServer() 创建新的服务器时,通常会实例化并返回此类 ,
  • close() 停止服务器不再接收新连接 listen() 启动HTTP服务器并监听连接
  • http.ServerResponse 由 http.Server 创建,并作为第二个参数传递给它触发的request事件
const server = http.createServer((req, res) => {
  //res 是一个 http.ServerResponse 对象。
})

在事件处理函数中总是会调用的方法是 end() ,它会关闭响应

  • getHeaderNames() 获取已设置的 HTTP 消息头名称的列表。
  • getHeaders() 获取已设置的 HTTP 消息头的副本。
  • setHeader('headername', value) 设置 HTTP 消息头的值。
  • getHeader('headername') 获取已设置的 HTTP 消息头。
  • removeHeader('headername') 删除已设置的 HTTP 消息头。
  • hasHeader('headername') 如果响应已设置该消息头,则返回 true。
  • headersSent() 如果消息头已被发送给客户端,则返回 true。

七、URL模块

URL一共提供了三个方法,分别是url.parse(),url.format(),url.resolve()。

url 模块中的 parse() 方法获取URL字符串,对其进行解析,然后返回 url 对象:

url.format()方法将传入的url对象编程一个url字符串并返回。

url.resolve()方法以类似于解决锚标记HREF的Web浏览器的方式来解析相对于基础URL的目标URL,返回一个格式为"from/to"的字符串。