node.js教程--持续更新中

node安装

进入node官网
在这里插入图片描述
第一个为长期支持的版本,可以理解成稳定版,第二个为发布版本,含有最新的功能。可根据需求下载安装。
下载完成后,打开文件选择路径即可安装。
***若需要切换不同的版本,则需要使用nvm

NVM安装使用教程

REPL

Node.js中REPL(交互式解释器) 表示一个电脑的环境,可以在终端输入命令,并接受响应

  • 读取(read) - 读取用户输入的js代码
  • 执行(exec)- 执行用户输入的js代码
  • 打印(print)- 打印用户输入的js代码
  • 循环(loop)- 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出

类似于浏览器的调试窗口,可执行简单的表达式运算,这里不多做解释。
附上一些常用的命令

  • ctrl + c 按下两次 - 退出 Node REPL
  • ctrl + d - 退出 Node REPL
  • 向上/向下 键 - 查看输入的历史命令
  • .help - 列出使用命令

在这里插入图片描述
在E盘放入一个hello.js,内容为console.log("hello"),执行终端

在这里插入图片描述

自定义模块

1.创建一个模块(一个js就是一个模块)
2.导出一个模块(module.exports=name)
3.引入一个模块并且调用(require)

这里用个例子来解释模块的导出以及导入
dog.js功能模块

let dog={
    dogname:'wangcai',
    say(){
        console.log('wangwang')
    }
}
module.exports=dog

main.js引用模块

//引入模块,赋值给cal
const Module=require('./dog')
console.log(Module.dogname);
Module.say()

终端执行

在这里插入图片描述

内置模块

文件操作

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

这里全部操作只讲解异步操作,同步操作请参照官方文档,同步操作中,可以用try catch语句捕获异常。

异步读取文件目录

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

参数 解释
path 路径
options 可选参数,encoding(可选编码默认UTF-8),withFileTypes(默认false))
callback 回调函数,err(为null则成功,否则返回错误信息),files(目录中的文件名的数组)

文件目录
在这里插入图片描述
代码

const fs=require('fs')
fs.readdir('./',(err,file)=>{
    //读取正确err为null,否则为错误信息
    if (err) throw err
       console.log(file)
})
fs.readdir('./dir',(err,file)=>{
    if (err) throw err
       console.log(file)
})

输出结果
在这里插入图片描述
创建目录

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

参数 解释
path 路径
options 可选参数,recursive(recursive 属性默认值: false),mode( Windows 上不支持默认值: 0o777)
callback 回调函数,err(为null则成功,否则返回错误信息)

代码

const fs=require('fs')
fs.mkdir('./test',(err)=>{
	if (err) throw err
       console.log('创建目录成功')
})

重命名

fs.rename(oldPath, newPath, callback

参数 解释
oldPath 原文件名字
newPath 重命名后的文件名字
callback 回调函数,err(为null则成功,否则返回错误信息)

代码

const fs=require('fs')
fs.rename('./test','./test1',(err)=>{
    if(err) throw err
    console.log("重命名成功")
})

写文件

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

参数 解释
file 文件名或文件描述符
data 写入的数据
options 可选参数,encoding(可选编码默认UTF-8),mode(模式),flag(文件系统标志默认w)
callback 回调函数,err为null则成功,否则返回错误信息
const fs=require('fs')
fs.writeFile('./test.txt','HelloWorld',['utf-8','w'],(err)=>{
    if (err) throw err
    console.log('文件写入成功')
})

读文件

fs.readFile(path[, options], callback)
参数 解释
path 文件路径
options 可选参数encoding(可选编码默认null),flag(文件系统标志默认r)
callback 回调参数,err(错误信息),data(返回的数据,如果没指定编码,返回原始的 buffer)
const fs=require('fs')
fs.readFile('./test.txt','utf-8',(err,data)=>{
   	if(err) throw err
    console.log(data)
})

删除文件

fs.unlink(path, callback)

代码

const fs=require('fs')
fs.unlink('./test.txt',(err)=>{
    if(err) throw err
    console.log('文件删除成功')
})

更多请点击fs官方文档

url处理

url 模块用于处理与解析 URL
在这里插入图片描述

url.parse在最新node中为遗留属性,这里不做讲解,采用URL类进行讲解

URL 类

new URL(input[, base])
参数 解释
input 要解析的绝对或相对的 URL。如果 input 是相对路径,则需要 base。 如果 input 是绝对路径,则忽略 base
base 如果 input 不是绝对路径,则为要解析的基本 URL

代码

const myURL = new URL('https://user:[email protected]:8080/p/a/t/h?query=string#hash')
console.log(myURL.href)//整个连接
console.log(myURL.protocol)//协议
console.log(myURL.username)//用户名
console.log(myURL.password)//密码
console.log(myURL.host)//主机
console.log(myURL.hostname)//主机名
console.log(myURL.port)//端口号
console.log(myURL.pathname)//路径名
console.log(myURL.search)//请求参数
console.log(myURL.hash)//哈希值
console.log(myURL.searchParams)//URL查询参数的URLSearchParams对象

结果
在这里插入图片描述
URLSearchParams 类
URLSearchParams API 提供对 URL 查询部分的读写权限

方法/属性 含义
.append(name, value) 在查询字符串中附加一个新的键值对
.delete(name) 删除所有键为name的键值对
.get(name) 返回键是name的第一个键值对的值。如果没有对应的键值对,则返回null
.getAll(name) 返回键是name的所有键值对的值,如果没有满足条件的键值对,则返回一个空的数组
.has(name) 如果存在至少一对键是 name 的键值对则返回 true
.set(name, value) 将 URLSearchParams 对象中与 name 相对应的值设置为 value。 如果已经存在键为 name 的键值对,则将第一对的值设为 value 并且删除其他对。 如果不存在,则将此键值对附加在查询字符串后
.toString() 返回查询参数序列化后的字符串,必要时存在百分号编码字符
.entries() 在查询中的每个键值对上返回一个 ES6 Iterator。 迭代器的每一项都是一个 JavaScript Array。 Array 的第一个项是键 name, Array 的第二个项是值 value
.keys() 在每一个键值对上返回一个键的 ES6 Iterator
.values() 在每一个键值对上返回一个值的 ES6 Iterator

代码

const myURL = new URL('https://user:[email protected]:8080/p/a/t/h?query=string#hash')
//.searchParams方法返回的已经是个URLSearchParams类
console.log(myURL.searchParams.get('query'))

//构建一个URLSearchParams类
let params = new URLSearchParams('a=1&a=2&b=3');

params.append('c', '3')
console.log(params.toString())

params.delete('b')
console.log(params.toString())

console.log(params.getAll('a'))

console.log(params.has('a'))

params.set('a', '4')
console.log(params.toString())

for(let arr of params.entries()){
    console.log(arr[0]+'-'+arr[1])
}

for (let name of params.keys()) {
    console.log(name);
}

for (let value of params.values()) {
    console.log(value);
}

结果
在这里插入图片描述
更多请点击url官方文档

第三方模块使用实例

npm的官网上,有许多第三方模块,这里以发送邮件的模块–nodemailer为例,讲述如何使用第三方模块
0.初始化npm项目
进入终端,执行npm init
在这里插入图片描述
输入命令后,分别填写项目信息,也可以不填,填写完成后输入yes。
1.首页搜索nodemailer
在这里插入图片描述
2.找到帮助文档或者官网
在这里插入图片描述
3.安装模块

npm install nodemailer

4.查看示例使用并且修改

'use strict';
//引入node模块
const nodemailer = require('nodemailer');
//创建发送邮件的对象
let transporter = nodemailer.createTransport({
    host: 'smtp.qq.com', //发送方邮箱类型主机号,通过node包里的well-known里services.json查询
    port: 465, //端口号
    secure: true, // 465端口为true, 其他端口为false
    /*通过well-known查询的qq邮箱信息
        "QQ": {
        "domains": ["qq.com"],
        "host": "smtp.qq.com",
        "port": 465,
        "secure": true
        },
     */
    auth: {
        user: '[email protected]', //发送方邮箱地址
        pass: 'xxxxxxxxx' //mtp验证码
    }
    /*
    qq邮箱mtp开启方法
    设置-账户-POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务
    开通POP3/SMTP服务,其他自行查找或百度
    */
});

transporter.sendMail({
    from: '"HelleWorld有限公司" <[email protected]>', // 发件方地址
    to: '[email protected],[email protected]', // 多个邮箱用逗号隔开
    subject: '验证码', // 主题
    text: '您的验证码信息是123456', // 文本信息
    html: '<b>您的验证码信息是123456</b>' // html信息,若使用text则html无效
});

简易爬虫

通过get方法获取目标网站,通过cheerio分析网站内容
1.数据处理部分

/*基本构架*/
//根据协议引入http或者https模块
const http=require('http')
let url='https://movie.douban.com/'
http.get(url,(res)=>{
    //数据分段,只有接受数据会触发data 事件chunk每次接受新的数据片段
    res.on('data',chunk=>{
        console.log('数据传输')
    })
    //数据传输完成
    res.on('end',()=>{
        console.log('数据传输完毕')
    })
}).on('error',(err)=>{
    console.log('请求错误')
})

案例:将豆瓣电影的网页爬取下来存在一个html页面下

const http = require('https')
const fs = require('fs')
let url = 'https://movie.douban.com/'
http.get(url, (res) => {
    //数据分段,只有接受数据会触发data 事件chunk每次接受新的数据片段
    let rawData = ''
    res.on('data', chunk => {
        rawData += chunk
    })
    //数据传输完成
    res.on('end', () => {
        fs.writeFile('./douban.html', rawData, (err) => {
            if (err) throw err
            console.log('文件写入成功')
        })
    })
}).on('error', (err) => {
    console.log(err)
})

2.安全判断

const http = require('https')
const fs = require('fs')
let url = 'https://movie.douban.com/'
http.get(url, (res) => {
    //状态码
    const { statusCode } = res
    //const statusCode=res.statusCode
    //请求头
    const contentType = res.headers['content-type']
    let error
    if (statusCode !== 200) {
        error = new Error('请求状态错误');
    } else if (!/^ text\/html/.test(contentType)) {
        //正则验证
        error = new Error('请求类型错误');
    }
    if (error) {
        console.log(error);
        res.resume();//清除缓存
        return false;
    }
}).on('error', (err) => {
    console.log(err)
})

3.分析网站内容
通过npm命令安装cheerio模块

npm install cheerio

类似于jq选择器选择元素

const cheerio = require('cheerio')
const $ = cheerio.load('<div class="box"><img src="pictruelink1"><img src="pictruelink2"></div>')
// 类似于jq选择器的各种用法
//$('.box').text('title')
//$('.box').addClass('welcome')
//console.log($.html())
$('img').each((index,el)=>{
    console.log(index)
    console.log($(el).attr('src'))
})

案例:将豆瓣电影所有图片地址爬取下来打印

const http = require('https')
const cheerio = require('cheerio')
let url = 'https://movie.douban.com/'
http.get(url, (res) => {
    //安全判断
    //状态码
    const { statusCode } = res
    //const statusCode=res.statusCode
    //请求头
    const contentType = res.headers['content-type']
    let error
    if (statusCode !== 200) {
        error = new Error('请求状态错误');
    } else if (!/^text\/html/.test(contentType)) {
        //正则验证
        error = new Error('请求类型错误');
    }
    if (error) {
        console.log(error);
        res.resume();//清除缓存
        return false;
    }

    //数据分段,只有接受数据会触发data 事件chunk每次接受新的数据片段
    let rawData = ''
    res.on('data', chunk => {
        rawData += chunk
    })
    //数据传输完成 
    res.on('end', () => {
        const $ = cheerio.load(rawData)
        $('img').each((index,el)=>{
            console.log($(el).attr('src'))
        })
        
    })
}).on('error', (err) => {
    console.log(err)
})

express框架

安装方式

	npm install express

HelloWorld

const express=require('express')
//express实例化
const app=express()
//get方法,接受前端的get请求
app.get('/',(req,res)=>{
    res.send('Hello World')
})
//监听9501端口,运行服务器
app.listen(9501,()=>{
    console.log('Server Start')
})

在浏览器运行http://localhost:9501/开始服务器

get接收参数
.query属性接收get方法传过来的数据

const express=require('express')
//express实例化
const app=express()
app.get('/login',(req,res)=>{
    //console.log(req.query)
    //打印结果
   	//{ username: 'bob', password: '123456' }
	let { username,password}=req.query
    if(username==='bob'&&password==='123456'){
        res.send({code:0,msg:'login success'})
 	}else{
       	res.send({code:-1,msg:'login fail'})
    }
})
app.listen(9501,()=>{
    console.log('Server Start')
})

在浏览器输入http://localhost:9501/login?username=bob&password=123456开启服务器查看运行结果
post接收参数
post解析参数需要用到body-parser插件
安装方法

	npm install body-parser

body属性接受post方法传递过来的参数

const express=require('express')
const bodypaser=require('body-parser')
//express实例化
const app=express()
//app.use为中间件的使用方法,见下文
//解析表单数据 application/x-www-form-urlencoded
app.use(bodypaser.urlencoded({ extended: false }))
//解析json格式数据 application/json
app.use(bodypaser.json())
app.post('/login',(req,res)=>{
    //console.log(req.body)
   	// { username: 'bob', password: '123456' }
    let { username,password}=req.body
    if(username==='bob'&&password==='123456'){
        res.send({code:0,msg:'login success'})
     }else{
        res.send({code:-1,msg:'login fail'})
    }
})
app.listen(9501,()=>{
    console.log('Server Start')
})

在这里插入图片描述

中间件
中间件就是在收到请求之后以及发出响应之前执行的一些函数,也可将其理解成一个拦截器。
原型为:

app.use([path,] function [, function…])

path如果为空,则默认为’/’
中间件分以下三种
1.内置中间件
express.static用来处理静态资源,是express的内置中间件,具体用如下

//在node里建立一个img文件夹放入pic.jpg
const express=require('express')
//引入path路径处理模块
const path=require('path')
const app=express()
//使用内置中间件
//__dirname为当前文件所在的目录,path中的join方法用于拼接路径
//app.use(express.static(path.join(__dirname,'./img')))
//访问http://localhost:9595/pic.jpg即可查看图片
app.use('/tupian',express.static(path.join(__dirname,'./img')))
//访问http://localhost:9595/tupian/pic.jpg即可查看图片
app.listen(9595,()=>{
    console.log('Server Start')
})

2.自定义中间件
自定义中间件的函数为function(req,res,next),可以为全局的,可以为局部的。next表示是否继续往下执行
例:多端口验证token(这里token先用一个随机的字符串表示)

const express=require('express')
const app=express()
//先进入中间件,判断传入的是否有一个参数为token有则往下执行,没有则返回结果,不往下执行
app.use('/',(req,res,next)=>{
    let {token}=req.query
    if(token){
        next()
    }else{
        res.send('缺少token')
    }
})
app.get('/test1',(req,res)=>{
    res.send('test1')
})
app.get('/test2',(req,res)=>{
    res.send('test2')
})
app.listen(9595,()=>{
	console.log('Server Start')
})
//访问http://localhost:9595/test1,显示缺少token
//http://localhost:9595/test2?token=fsdklv,显示test2

例:路由的封装
express.Router()方法封装路由,封装路由可以让工程模块化。
建立一个router.js

const express=require('express')
//express.Router()方法封装路由
const router=express.Router()
router.get('/login',(req,res)=>{
    res.send("this is login")
})
router.get('/register',(req,res)=>{
    res.send("this is register")
})
//导出router
module.exports=router

main.js

const express=require('express')
//引入路由
const userRouter=require('./router')
const app=express()
//中间件,路径为/user进入封装好的路由
app.use('/user',userRouter)
app.listen(9595,()=>{
   console.log('Server Start')
})
//访问http://localhost:9595/user/login 显示this is login
//访问http://localhost:9595/user/register,显示this is register

3.第三方中间件
上文中使用body-parser插件就是第三方中间件的用法

mysql

安装mysql依赖

npm install mysql

数据库连接

var mysql = require('mysql');
var connection = mysql.createConnection({
    host: 'localhost',//主机地址 (默认:localhost)
    user: 'root',//用户名
    password: 'logan123',//密码
    database: 'testDB'//数据库名
});
//连接数据库
connection.connect((err) => {
    if (err) throw err
    console.log('数据库连接成功')
});
//断开数据库
connection.end();

更多配置

sql语句操作。
具体的sql语句的用法这边不做讲解,以查询数据和插入数据为例。
user数据表
在这里插入图片描述

var mysql = require('mysql');
var connection = mysql.createConnection({
    host: 'localhost',//主机地址 (默认:localhost)
    user: 'root',//用户名
    password: '******',//密码
    database: 'testDB'//数据库名
});
//连接数据库
connection.connect((err) => {
    if (err) throw err
    console.log('数据库连接成功')
});
connection.query("select * from user",(err, result)=>{
    if(err) throw err
    console.log(result)
})
connection.query("insert into user values(4,'rose','789654')",(err, result)=>{
    if(err) throw err
    console.log(result)
})
//断开数据库
connection.end();

执行结果
在这里插入图片描述
user表
在这里插入图片描述
防sql注入

var mysql = require('mysql');
var connection = mysql.createConnection({
    host: 'localhost',//主机地址 (默认:localhost)
    user: 'root',//用户名
    password: '******',//密码
    database: 'testDB'//数据库名
});
//连接数据库
connection.connect((err) => {
    if (err) throw err
    console.log('数据库连接成功')
});
let addsql="insert into user values(?,?,?)"
let addSqlParams = [4, 'rose','789654'];
connection.query(addsql,addSqlParams,(err, result)=>{
    if(err) throw err
    console.log(result)
})
//断开数据库
connection.end();

解决跨域

cors模块

express中可用cors来解决跨域问题
安装方法

npm install cors

使用

const cors=require('cors')
const app=express()
app.use(cors())

文件上传

安装multer模块

npm install multer

配置storage(磁盘存储引擎)

const storage = multer.diskStorage({
	destination: (req, file, cb) => {
		//cb第二个参数为存储的路径
		cb(null, './upload')
	},
	filename: (req, file, cb) => {
		//cb第二个参数为文件的名字
		cb(null, file.originalname)
	}
})

实例化multer

const upload = multer({
	storage: storage
});

post方法使用

//.single为单个文件上传。键名为'key'
app.post('/upload', upload.single('key'), (req, res) => {
	res.send('ok');
})

优化代码
1.设置上传文件大小数量限制

const uploadConfig = multer({
	limits:{
        fileSize: 50*1024,
        //上传文件数
        files: 5,
    }
 }
//若文件大小不正确,则会抛出一个错误

2.设置文件上传类型

const uploadConfig = multer({
	limits:{
        fileSize: 50*1024,
        files: 5
    },
	fileFilter:(req,file,cb)=>{
		if(file.mimetype == 'image/jpeg'||file.mimetype == 'image/jpg'){
            cb(null, true)
        } else {
            cb(null, false)
            //抛出一个错误
		    cb(new Error())
		}
	}
})
//这里若文件类型不正确,则不会接收,但是不会抛出错误,所以需要手动抛出一个错误

完整代码

const uploadConfig = multer({
	limits: {
		fileSize: 100*1024,
		files: 5
	},
	storage: multer.diskStorage({
		destination: (req, file, cb) => {
			//cb第二个参数为存储的路径
			cb(null, './upload')
		},
		filename: (req, file, cb) => {
			//截取文件的后缀名
			let exts = file.originalname.split('.')
			//取最后一个元素
			let ext = exts[exts.length - 1]
			//文件名为时间戳加上4个随机数字
			let filename = (new Date()).getTime()
			let randnum = parseInt(1000 + Math.random() * 8999)
			cb(null, `${filename}${randnum}.${ext}`)
		}
	}),
	fileFilter: (req, file, cb) => {
		if (file.mimetype == 'image/jpg' || file.mimetype == 'image/jpeg') {
			cb(null, true)
		} else {
			cb(null, false)
			//抛出一个错误
			cb(new Error())
		}
	}
})

let upload = uploadConfig.single('key')

app.post('/upload', (req, res) => {
	upload(req, res, (err) => {
		if (err instanceof multer.MulterError) {
			return res.send(err.message)
		} else if (err) {
			//此处接收文件类型限制抛出的错误
			return res.send("type error")
		}
		res.send("sucess")
	})
})

JWT

JSON Web Token基于Token的身份验证
安装

npm install jsonwebtoken

生成token

jwt.sign(payload, secretOrPrivateKey, [options, callback])

payload-存储加密信息
secretOrPrivateKey-key,加密的钥匙
expiresIn-设置有效期,不带单位默认为秒。也可以是时间跨度字符串

let payload={
	us:'test',
	ps:'123456'
}
let secretOrPrivateKey="dsadas"
jwt.sign(payload,secretOrPrivateKey, {expiresIn:60*60},(err,token)=>{
	if(err) throw err
	console.log(token)
})

解密token

jwt.verify(token, secretOrPublicKey, [options, callback])

token-由jwt.sign生成的token
secretOrPrivateKey-加密的key,用于解析token的payload里的信息

let token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cyI6IjEyMyIsInBzIjoiMTIzIiwiaWF0IjoxNTc1MzQyNjI4LCJleHAiOjE1NzU0MjkwMjh9.Fk7w2zeve5NNLYRJpt3ErIR0INvpFgpdi_4oNr9xju0"
let secretOrPrivateKey="dsadas"
jwt.verify(token, secretOrPrivateKey, (err, data) =>{
	if(err.name==="TokenExpiredError"){
		console.log("token过期")
	}else if(err.name==="TokenExpiredError"){
		console.log("无效的token")
	}
	else{
		console.log(data)
	}
})
发布了20 篇原创文章 · 获赞 25 · 访问量 7460

猜你喜欢

转载自blog.csdn.net/qq_41866776/article/details/101309756
今日推荐