文章目录
- 学习总结
- nodejs基础知识
- 核心模块(内置模块)
- fs(file-system)文件系统
- fs增删查改
- url
- Query String
- http
- request
- 根据不同的请求路径发送不同的响应结果
- require
- ip地址和端口号
- Content-Type
- 第三方模块
- express
- 登录接口逻辑分析
- express的基本使用
- 服务器相关
- 服务器:
- api接口构成要素
- postman 接口测试
- api接口书写
- middlewear 中间件
- 静态资源目录 static
- 路由
- 异步回调 promise
- 生活总结
学习总结
nodejs基础知识
核心模块(内置模块)
是一个JS运行时的环境,简单来说就是Node.js可以解析执行JS代码
Node.js中的JS没有BOM、DOM;在Node这个JS执行环境中为JS提供了一些服务器级别的操作API
例如:文件读写、网络服务的构建、网络通信、http服务器等的处理
fs(file-system)文件系统
在Node中如果执行文件操作必须引入fs这个核心模块;在fs这个核心模块中,就提供了所有的文件操作相关的API
var fs = require('fs')
fs.mkdir(path,callback) 创建文件夹
fs.rename() 更改文件名
fs.rmdir(path,callback) 删除文件夹,文件夹只能是空的
fs.stat() 判断是文件还是文件夹
fs.stat('./node01',(err,stats)=>{if(stats.isFile()){console.log('is file)}else{console.log('is dir')}
})
fs增删查改
fs.readFile用来读取文件的
// 读文件异步
// 成功
// date 数据
// error null
// 失败
// date undefined没有数据
// error 错误对象
// 同步错误处理
// try catch
fs.readFile('./date/helloWorld.txt',function(error,date){console.log(date.toString())
})
fs.writeFile() 用来创建文件的
// 写文件
// 成功
// 文件写入成功
// error 是 null
// 失败
// 文件写入失败
// error就是错误对象fs.writeFile('./date/你好.md','大家好,我是檀健次老婆',function(error){console.log('文件成功写入')if(error){console.log('写入失败')}else{console.log('写入成功')}
})
fs.appendFile() 用来写入文件fs.appendFile('./date/你好.md','大家好,我是檀健次老婆',function(error){console.log('error')
})
fs.unlink() 用来删除文件fs.unlink('./date/你好.md','大家好,我是檀健次老婆',function(error){console.log('error')
})
url
url.parse() 将url字符串转成对象const url = require('url')
let urlString = 'https:47.95.207.1:3000/fcj/recommend/hot/hehe?us=123&ps=567#nihao'
let urlObj = url.parse(urlString)
console.log(urlObj)
url.format() 将url对象转成字符let obj = {protocol: 'https:',slashes: null,auth: null,host: null,port: null,hostname: null,hash: '#nihao',search: '?us=123&ps=567',query: 'us=123&ps=567',pathname: '47.95.207.1:3000/fcj/recommend/hot/hehe',path: '47.95.207.1:3000/fcj/recommend/hot/hehe?us=123&ps=567',href: 'https:47.95.207.1:3000/fcj/recommend/hot/hehe?us=123&ps=567#nihao'}let string = url.format(obj)console.log(string)
Query String
querystring.parst() 将字符串变成对象
querystring.stringify() 将对象变成字符串const qs = require('querystring')
let string = 'name=mq&pass=123&sex=0'
// 两种写法
let obj = qs.parse(string)
let obj = qs.parse(string,'&','=')
console.log(obj)
const qs = require('querystring')
let obj = { name: 'mq', pass: '123', sex: '0'}
let string = qs.stringify(obj,'^','?')
console.log(string)
qs.escape() 编码操作
qs.unescape() 解码操作
http
在Node中专门提供了一个核心模块:http
职责就是创建编写服务器
// 1. 加载http
var http = require('http')// 2.使用http.createServer()方法创建一个Web服务器
// 返回一个Server实例
var server = http.createServer()// 3.服务器
// 提供服务:对数据的服务
// 发送请求
// 接受请求
// 处理请求
// 发送响应
// 注册 request请求事件
// 当客户端请求过来,就会自动触发服务器的request请求事件,然后执行第二个参数;回调处理函数
server.on('request',function(){console.log('收到客户端的请求了')
})// 4.绑定端口号,启动服务器
server.listen(3000,function(){console.log('服务器启动成功了,可以通过http://127.0.0.1:3000/ 来访问')
})
request
请求事件处理函数,需要接收两个参数:
- Request 请求对象
请求对象可以用来获取客户端的一些请求信息,比如请求路径 - Response 响应对象
响应对象可以用来给客户端发送响应消息
有一个方法write可以用来给客户端发送响应数据;write可以多次使用,但是最后一定要使用end来结束响应,否则客户端会一直等待
server.on('request',function(request,response){console.log('收到客户端的请求了,请求路径是' + request.url)response.write('hello nodejs')response.end()// 简单写法response.end('hello nodejs')
})
根据不同的请求路径发送不同的响应结果
- 获取请求路径
req.url获取到的是端口号之后的那一部分路径;所有的url都是以/开头的 - 判断路径处理响应
server.on('request',function(req,res){var url = req.urlconsole.log(url)if(url === '/' ){res.end('index page')}else if(url === '/Login'){res.end('Login page')}else{res.end('404 Not Found.')}
})
server.on('request', function (req, res) {var url = req.urlif (url === '/products') {var products = [{name: '苹果 15',price: 9999},{name: '菠萝 15',price: 5000},{name: '小辣椒 15',price: 1999},]// 响应内容只能是二进制数据或字符串res.end(JSON.stringify(products))}
})
require
是一个方法
作用
一、是用来加载模块并执行里面的代码的;
在Node中,模块有三种:
具名的核心模块,例如 fs http
用户自己编写的文件模块 相对路径必须加 ./ 可以省略后缀名
在Node中没有全局作用域,只有模块作用域(文件作用域)
- 外部访问不到内部
- 内部也访问不到外部
- 默认都是封闭的
var foo = 'aaa'
console.log('a start')
require('./b.js')
console.log('a end')
console.log('foo的值是:' + foo)
console.log('b start')
var foo = 'bbb'
require('./c.js')
console.log('b end')
console.log('ccc')
二、拿到被加载文件模块导出的接口对象
每个文件模块中都提供了一个对象:exports
exports 默认是一个空对象
var bExports = require('./b')
var fs = require('fs')
console.log(bExports.foo)
console.log(bExports.add(10,30))bExports.readFile('./a/js')fs.readFile('./a.js',function (err,date) {if(err){console.log('读取文件失败')}else{console.log(date.toString())}
})
var foo = 'bbb'
exports.foo = 'hello'
exports.add = function(x,y){return x + y
}exports.readFile = function(path,callback){console.log('文件路径:',path)
}
ip地址和端口号
IP地址用来定位计算机
端口号用来定位具体的应用程序
所有需要联网通信的应用程序都会占用一个端口号
Content-Type
在服务器默认发送的数据是utf-8编码的内容,但浏览器不知道,中文操作系统默认是gbk
不同的资源对应的Content-Type是不一样,具体参照:http://tool.oschina.net/commons
对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
在http协议中,Content-Type就是用来告知对方我给你发送的数据内容是什么类型
var http = require('http')
var server = http.createServer()
server.on('request',function(req,res){res.setHeader('Content-Type','text/plain;charset=utf-8')res.end('hello 檀健次')
})
server.listen(3000,function(){console.log('Server is running...')
})
如果发送的是html格式的字符串,则也要告诉浏览器我发送的是text/html格式的内容
var http = require('http')
const { default: test } = require('node:test')
var server = http.createServer()
server.on('request',function(req,res){// res.setHeader('Content-Type','text/plain;charset=utf-8')// res.end('hello 檀健次')var url = req.urlif(url === '/plain'){res.setHeader('Content-Type','text/plain;charset=utf-8')res.end('hello 檀健次')}else if(url === '/html'){res.setHeader('Content-Type','text/html;charset=utf-8')res.end('<p>hello html<a>点我</a></p>')}
})
server.listen(3000,function(){console.log('Server is running...')
})
通过网络发送文件
- 发送的并不是文件,本质上来讲发送是文件的内容
- 当浏览器收到服务器响应内容之后,会根据你的Content-Type进行对应的解析处理
var fs = require('fs')
var http = require('http')
const { default: test } = require('node:test')
var server = http.createServer()
server.on('request',function(req,res){var url = req.urlif(url === '/'){fs.readFile('./resource/index.html',function(err,data){if(err){res.setHeader('Content-Type','text/plain;charset=utf-8')res.end('文件读取失败,请稍后重试!')}else{res.setHeader('Content-Type','text/html;charset=utf-8')res.end(data)}})}else if(url === '/a'){fs.readFile('./resource/aaa.jpg',function(err,data){if(err){res.setHeader('Content-Type','text/plain;charset=utf-8')res.end('文件读取失败,请稍后重试!')}else{res.setHeader('Content-Type','image/jpeg')res.end(data)}})}})
server.listen(3000,function(){console.log('Server is running...')
})
第三方模块
nodemailer 可以实现发邮件
npm install jquery --save
npm官网 [http://www.npmjs.com/]
const nodemailer = require("nodemailer");// 创建发送邮件的对象
const transporter = nodemailer.createTransport({host: "smtp.ethereal.email", // 发送方邮箱 通过lib/well-known/services.jsonport: 587, // 端口号secure: false, // Use `true` for port 465, `false` for all other portsauth: {user: "maddison53@ethereal.email", // 发送方的邮箱地址pass: testAccount.pass, // mpt 验证码},
});// 邮件信息
let mailobj = {from: '"Maddison Foo Koch 👻" <maddison53@ethereal.email>', // sender addressto: "bar@example.com, baz@example.com", // list of receiverssubject: "Hello ✔", // Subject linetext: "Hello world?", // plain text bodyhtml: "<b>Hello world?</b>", // html body
}// 发送邮件
transporter.sendMail(mailobj,(err,data)=>{console.log(err)console.log(data)
})
express
登录接口逻辑分析
1.接收用户传递数据
2.处理数据
3.返回数据
express的基本使用
1.安装
npm install express -save
第三方模块引用,从当前目录的node——modules以此向上寻找
2.简单使用
const express = require('express')
const app = express()
// express 实例化// 最简单的api接口
app.get('/user/login',(req,res)=>{console.log('你好')res.send({err:0,msg:'regist ok'})
})
app.listen(3000,()=>{// 监听3000端口 开启服务器console.log('server start')
})
服务器相关
服务器:
1.服务器就是一台电脑
2.服务器软件(apach tomcat iis ngnix node)
3.服务器IP 和端口号
局域网:服务器通过网线(无线)连接,每个电脑都会有一个ip
外网:
ip:确定服务器主机的位置
port:确定服务器里某个应用程序
api接口构成要素
ip
port
pathname 语义化,见文知意
method get post
接收用户传递数据 数据格式由后端确定的
postman 接口测试
api接口书写
接受数据
- get req.query
- post req.body 需要body-parser 插件进行解析
- 注意数据格式 json x-www-form-urencode formdata
const express = require('express')
const app = express()
// express 实例化
const bodypaser = require('body-parser')
// app.use 使用中间插件
// 解析表单数据
// 解析form表单
app.use(bodypaser.urlencoded({extended:false}))
// 解析json 数据
app.use(bodypaser.json())// 最简单的api接口
app.get('/user/login',(req,res)=>{// 接收get参数 req.queryconsole.log(req.query)console.log('你好')let {us,ps} = req.query// 处理参数if(us === 'mq' && ps == 456){res.send({err: 0,msg:'regist ok'})}else{res.send({err: -1,msg:'us pass no ok'})}})app.post('/user/reg',(req,res)=>{// 接收post数据 消息体 请求体 req.bodylet {us,ps} = req.bodyconsole.log(req.body)// express 不能直接解析消息体// 通过第三方插件实现解析if(us == 123 && ps == 123){res.send({err: 0,msg:'regist ok'})}else{res.send({err: -1,msg:'us pass no ok'})}})app.listen(3000,()=>{// 监听3000端口 开启服务器console.log('server start')
})
middlewear 中间件
内置中间件 static
自定义中间件(全局 局部)
第三方中间件 (body-parser)(拦截器)
中间件使用 一定注意next
const express = require('express')
const app = express()
// 拦截器
app.use('/',(req,res,next)=>{console.log('中间件')let {token} = req.queryif(token){next() // 是否继续往下执行}else{res.send('缺少token')}
})app.get('/test1',(req,res)=>{console.log('test1')// let {token} = req.query// if(token){// res.send('ok')// }else{// res.send('no ok')// }res.send('test1')
})app.get('/test2',(req,res)=>{console.log('test2')// let {token} = req.query// if(token){// res.send('ok')// }else{// res.send('no ok')// }res.send('test2')
})app.listen(3000,()=>{console.log('server start')
})
const express = require('express')
const app = express()app.get('/test1',(req,res,next)=>{console.log('fun1')next()
},s
(req,res)=>{console.log('fun2')res.send('test1')
})
// app.get('/pathname',fun,fun,...)app.listen(3000,()=>{console.log('server start')
})
静态资源目录 static
指定一个目录,目录可以被访问
const express = require('express')
const path = require('path')
const app = express()
console.log(__dirname) // 当前文件所在的绝对路径
console.log(path.join(__dirname,'./data')) // 拼接路径
app.use(express.static(path.join(__dirname,'./data'))) // 写法一
app.use('/',express.static(path.join(__dirname,'./data'))) // 写法二
app.listen(3000,()=>{console.log('server static')
})
路由
user/add
user/del
food/add
food/del
const express = require('express')
const app = express()
// app.get('/user/add',(req,res)=>{
// res.send('user/add ok')
// })
// app.get('/user/del',(req,res)=>{
// res.send('user/del ok')
// })let userRouter = require('./router/userRouter')
let foodRouter = require('./router/foodRouter')
app.use('/user',userRouter)
app.use('/food',foodRouter)app.listen(3000,()=>{console.log('server static')
})
const express = require('express')
const router = express.Router() //获取路由的实例router.get('/add',(req,res)=>{res.send('food add')
})
router.get('/del',(req,res)=>{res.send('food del')
})module.exports = router
const express = require('express')
const router = express.Router() //获取路由的实例router.get('/add',(req,res)=>{res.send('food add')
})
router.get('del',(req,res)=>{res.send('food del')
})module.exports = router
异步回调 promise
1.封装promise 解决回调地狱
function test(){// 返回promisereturn new Promise((resolve,reject)=>{// 需要的异步处理成功的时候 resolve失败的时候 reject})
}
2.根据顺序 形成链式调用
test( ).then( ).then( ).catch( )
3.捕获错误
const { rejects } = require('assert')
const { promises } = require('dns')
const fs = require('fs')
const { resolve } = require('path')
function isEixt(){return new Promise((resolve,reject)=>{fs.stat('./hehe.js',(err,stats)=>{if(err){reject('文件不存在')}else{resolve('文件存在')}})})
}function delFile(){return new Promise((resolve,reject)=>{fs.unlink('./hehe.js',(err)=>{if(err){reject('del no ok')}else{resolve('del ok')}})})
}isEixt()
.then(()=>{console.log('is exit 的成功处理')return delFile()
})
.then(()=>{console.log('删除文件的成功处理')
})
.catch((err)=>{console.log('chatch')console.log(err)
})
注:一组链式调用中只需要一个catch;如何手动终止链式调用的执行 抛出一个错误
.then(()=>{console.log('删除文件的成功处理')throw new Error('手动终止')
})
生活总结
项目结束,没有那么赶,这周倒是不那么忙了,时间不是很紧迫了,nodejs有些偏后端,对于自己来说还是不太好学的,还是得下点功夫,这次的考核,要自己写接口和页面,不是很简单,亚历山大。周末突然加了认知实习,还要手写两千字总结,真的没什么意义啊啊啊啊啊,还浪费时间,我好不容易盼来的周末假期,,真的够了。。。