avatar

目录
NodeJs学习笔记

Node.js

  • Node.js只是一个运行平台(环境)

  • 插件nodemon 可以监听代码变化执行

基础知识

什么是I/O

+ input/output(输入/输出)

异步操作

  • Node 采用 chrome V8 引擎处理js脚本,
  • V8最大特点就是单线程运行,一次只能运行一个任务(堵塞)

错误优先

  • 因为node的大多数操作都是异步的方式,无法通过try,catch捕获异常
  • 所以设计回调函数的第一个参数都为上一步的错误信息(error)

进程与线程

  • 进程(进行中的程序)

  • 扩展

Code
1
2
3
在其他平台的多线程处理:
当有一个需要耗时的操作(阻塞)时,会开辟一个新的线程来进行操作
有多少个就开辟多少个,但是会吃CPU的性能
  • 事件队列
Code
1
2
Node是一个单线程的东西,遇到耗时的操作会放到事件队列例
事件队列会把一系列耗时的代码一步步往下执行
  • V8对ES6支持情况分为三种:
    • 根本不支持
    • 直接支持
    • 严格模式支持(use strict)

require扩展名

  • 例:require(‘./module’)
    • 如果不写扩展名先执行当前目录下同名的JS文件
    • 如果没有同名的JS文件,就会加载同名的JSON文件
    • 如果没有同名的JSON文件,就会去加载node文件(C++编译的文件)
    • 如果JS,JSON,node文件都没有,就会去加载同名的目录
      • 如果有package.json文件,并且里面的main属性指向了一个JS文件
      • 如果上面不成立就执行目录下的index.js

高并发

Node是非阻塞I/O

同步和异步

有些方法可能会有一个同步的API和异步的API

异步的API会有一个回调函数来

同步的API会把对象当作返回值

Node模块化开发

当exports对象和module.exports对象指向的不是同一个对象时,以module.exports为准

process(进程)

process.arch

查看为其编译Node.js二进制文件的操作系统的CPU架构

Code
1
console.log(process.arch)

process.argv

返回一个数组,其中包含启动NodeJs进程传入的命令行参数

Code
1
2
3
4
5
当启动NodeJs进程时
$ node first.js one two three

输出如下:
["node的安装路劲","文件的路劲","one","two","three"]
  • process.stdout.write()

    • 用于在控制台输出内容
  • process.stdin.on()

    • 标准输入
  • process.argv.forEach()

    • 返回的是一个数组,当启动node.js时输入的参数
    • first arguments: node.js of path
    • second arguments: file(js) of path
    • 。。。。。。。
  • process.debugPort

    • 查看node调试器使用的端口
    • 即可查看也也可赋值
  • process.exit([code])

    • 终止进程
  • process.platform

    • 返回的是node.js运行在哪个操作系统
  • process.uptime()

    • 获取node.js运行的时间

fs(文件系统)

fs模块提供了一个API,用于以模仿标准POSIX函数的方式与文件系统进行交互

  • 引入模块:const fs = require("fs");

fs.appendFile(path, data[, options], callback)

异步地将数据追加到文件,如果文件尚不在则创建文件

javascript
1
fs.appendFile("data.txt","appendData","utf8",(err)=>{})

fs.copyFile(src, dest[, flags], callback)

异步地将 src 拷贝到 dest。 默认情况下,如果 dest 已经存在,则覆盖它。 除了可能的异常,回调函数没有其他参数。 Node.js 不保证拷贝操作的原子性。 如果在打开目标文件用于写入后发生错误,则 Node.js 将尝试删除目标文件

javascript
1
fs.copyFile("source.txt","target.txt",(err)=>{})

fs.mkdir(path[, options], callback)

异步地创建目录。除了可能异常,完成回调没有其他参数

javascript
1
fs.mkdir("./newDir")

fs.readdir(path[, options], callback)

异步的读取目录的内容,回调有两个参数,其中files是目录中的文件名数组

fs.readFile(path[, options], callback)

异步的读取文件的全部内容

javascript
1
2
3
4
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});

fs.writeFile(path,data[, options],callback)

异步的将数据写入文件

javascript
1
fs.writeFile("./data.txt","hello world","utf8",(err)=>{})

异步的删除文件,除了可能的异常,完成回调没有其他参数

javascript
1
2
3
4
fs.unlink('path/file.txt', (err) => {
if (err) throw err;
console.log('文件已删除');
});

path(路劲)

path 模块提供用于处理文件路径和目录路径的实用工具

  • 引入模块:const path = require('path');

  • __dirname:返回当前文件的目录

  • __filename:返回当前文件的路劲+文件名

path.basename(path[,ext])

path.basename() 方法返回 path 的最后一部分,类似于 Unix 的 basename 命令

javascript
1
2
3
4
5
path.basename('/foo/bar/baz/asdf/quux.html');
// 返回: 'quux.html'

path.basename('/foo/bar/baz/asdf/quux.html', '.html');
// 返回: 'quux'

path.dirname(path)

path.dirname() 方法返回 path 的目录名,类似于 Unix 的 dirname 命令。

javascript
1
2
path.dirname('/foo/bar/baz/asdf/quux');
// 返回: '/foo/bar/baz/asdf'

path.extname(path)

path.extname() 方法返回 path 的扩展名,从最后一次出现 .(句点)字符到 path 最后一部分的字符串结束

javascript
1
2
3
4
5
6
7
8
9
10
11
path.extname('index.html');
// 返回: '.html'

path.extname('index.coffee.md');
// 返回: '.md'

path.extname('index.');
// 返回: '.'

path.extname('index');
// 返回: ''

path.parse(path)

path.parse() 方法返回一个对象,其属性表示 path 的重要元素。

Code
1
2
3
4
5
6
7
path.parse('C:\\path\\dir\\file.txt');
// 返回:
// { root: 'C:\\',
// dir: 'C:\\path\\dir',
// base: 'file.txt',
// ext: '.txt',
// name: 'file' }

path.format(pathObject)

path.format() 方法从对象返回路径字符串。 与 path.parse() 相反。

javascript
1
2
3
4
5
path.format({
dir: 'C:\\path\\dir',
base: 'file.txt'
});
// 返回: 'C:\\path\\dir\\file.txt'

path.join([…paths])

path.join() 方法使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径。

Code
1
2
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'

path.resolve([…paths])

path.resolve() 方法将路径或路径片段的序列解析为绝对路径。

path.relative(from, to)

path.relative() 方法根据当前工作目录返回 fromto 的相对路径。

Code
1
2
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');
// 返回: '..\\..\\impl\\bbb'

http(网咯)

http.createServer([options] [, requestListener] )

  • const http = require(‘http’)

    • 获取服务器模块
  • const server = http.createServer(callback(request,response))

    • 创建一个服务器
  • server.listen(port,callback(error))

    • 监听端口

stream(流)

概念

  • 流是一组有序的,有起点和终点的字节数据传输手段
  • 它不关心文件的整体内容,只关注是否从文件中读到了数据,以及读到数据之后的处理
  • 流是一个抽象接口,被 Node 中的很多对象所实现。比如HTTP 服务器request和response对象都是流

可读流

创建可读流

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
const fs = require('fs');   // 引入fs核心模块

// fs.createReadStream(path, options)
// 返回的是一个可读流对象
let rs = fs.createReadStream('1.txt', {
flags: 'r', // 文件的读取操作,默认是'r':读取
encoding: 'utf8', // 设置编码格式,默认是null, null代表的是buffer
autoClose: true, // 读取完毕后自动关闭
highWaterMark: 3, // 默认是读取64k 64 * 1024字节
start: 0,
end: 3 // 文件结束位置索引,和正常的截取slice有所不同,包前又包后(包括自己结束的位置)
});

监听data事件

Javascript
1
2
3
rs.on("data",data => {
console.log(data);
})

监听end事件

Javascript
1
2
3
rs.on("end",() => {
console.log("end")
})

监听error/open/close事件

Javascript
1
2
3
4
5
6
7
8
9
rs.on("error",err => {
console.log(err)
})
rs.on("open",() => {
console.log("file open")
})
fs.on("close",() => {
console.log("file close")
})

暂停和恢复

Javascript
1
2
3
4
5
6
7
rs.on("data",data => {
console.log(data);
rs.pause();
})
setInterval(()=>{
rs.resume();
},2000)

可写流

Javascript
1
2
3
4
5
6
7
8
const fs = require("fs");
const ws = fs.createWriteStream('2.txt', {
flags: 'w', // 文件的操作, 'w'写入文件,不存在则创建
mode: 0o666,
autoClose: true,
highWaterMark: 3, // 默认写是16k
encoding: 'utf8'
});

write方法

Javascript
1
2
3
4
5
6
7
8
9
// ws.write(chunk, encoding(可选), callback);
// 写入的chunk数据必须是字符串或者buffer
let flag = ws.write('1', 'utf8', () => {}); // 异步的方法 有返回值

console.log(flag); // true
flag = ws.write('22', 'utf8', () => {});
console.log(flag); // false 超过了highWaterMark的3个字节,不能再写了
flag = ws.write('3', 'utf8', () => {});
console.log(flag); // false

end方法

Javascript
1
ws.end("end");

监听drain事件

Javascript
1
2
3
ws.on("drain",() => {
console.log("完毕")
})

NodeJs常用框架

  • express:封装NodeJs常用的功能,造轮子
  • koa2:封装NodeJs常用的功能,造轮子
  • mysql:让NodeJs连接到MySQL数据库

NodeJs爬虫

爬虫的原理

访问服务器 -> 下载页面 -> 分析页面 -> 提取信息 -> 保存数据

在nodeJs原生的http模块的get请求是会把一整个网页给请求下来

robots.txt是一个文本文件,robots.txt是一个协议,不是一个命令。robots.txt是爬虫要查看的第一个文件。robots.txt文件告诉爬虫再服务器上什么文件是可以被查看的,搜索机器人就会按照该文件中的内容来确定访问的范围

request.js

NodeJS中的ajax

iconv-lite

在爬取页面的时候,经常会遇到编码格式的问题,导致页面中的文字乱码,我们需要借助这个框架来进行转码

puppeteer

cheerio

在server上的jquery

具体实现:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const iconv = require("iconv-lite");
const cheerio = require("cheerio");
const request = require("request");


// 爬取游民星空的壁纸分享圈子的壁纸
request("https://club.gamersky.com/activity/408552?club=108", { encoding: null }, (err, response, body) => {

if (response.statusCode == 200) {
// 请求成功

const bufs = iconv.decode(body, "gb2312");
const html = bufs.toString("utf8");
const $ = cheerio.load(html)

$(".picimg img").each((index, item) => {

console.log(item.attribs["data-origin"])

})



}

})
``

服务端验证

  • 通过cookie在客户端记录状态
  • 通过session在服务器端记录状态
  • 通过token方式维持状态

如果有跨域问题就使用token的方式来维持

token原理分析

客户端 ➡ 发起登录请求 ➡ 服务器验证之后生成该用户的token并返回 ➡ 客户端存储该token ➡ 后续的请求都携带该token发起请求 ➡ 服务端验证token是否存在/通过

文章作者: 青空
文章链接: https://gitee.com/AIR-ZRB/blog/2020/03/16/NodeJs-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 青空
打赏
  • 微信
    微信
  • 支付寶
    支付寶