Promise
Promise的介绍
Promise是异步编程的一种解决方案,它的构造函数是同步执行的,then 方法是异步执行的,所以Promise创建后里面的函数会立即执行,构造函数中的resolve和reject只有第一次执行有效,,也就是说Promise状态一旦改变就不能再变
Promise是异步编程的一种解决方案,它的构造函数是同步执行的,then 方法是异步执行的,所以Promise创建后里面的函数会立即执行,构造函数中的resolve和reject只有第一次执行有效,,也就是说Promise状态一旦改变就不能再变
const mysql = require('mysql')
const mysqlCnn = mysql.createConnection({
user: "admin",
password: "Mm2332868127.",
host: "localhost",
database: "bilibili"
})
mysqlCnn.connect(err=>{
if(err){
console.warn(`连接mysql数据库失败!错误原因为: ${err}`)
}else{
console.log("连接mysql服务器成功!")
}
})
// // 增
// mysqlCnn.query("INSERT INTO user (user_id, account, password) VALUES (223456, 'Tom3323', '12345678')", (err, result)=>{
// if(err){
// console.log(`数据更新出错!错误信息为: ${err}`)
// }
// })
// // 删
// mysqlCnn.query("DELETE FROM user WHERE user_id = 11111", err=>{
// if(err){
// console.log(`数据更新出错!错误信息为: ${err}`)
// }
// })
// // 改
// mysqlCnn.query("UPDATE user SET account = 'jerry', password = '333333' WHERE user_id = 11111 ", (err, result)=>{
// if(err){
// console.log(`数据更新出错!错误信息为: ${err}`)
// }
// })
// // 查
// mysqlCnn.query(SELECT * FROM user WHERE account='tomweichat@qq.com' and password='12345678' , (err, result)=>{
// if(err){
// console.log(`数据更新出错!错误信息为: ${err}`)
// }
// })
// 断开连接
mysqlCnn.release()
module.exports = mysqlCnn
session类似服务器端的cookie,保存于服务器端,类似于服务器缓存。用户登陆了总需要验证吧,那么就在session中验证即可,session和cookie是一一对应关系。
session的创建顺序
生成全局唯一标识符(sessionid);
开辟数据存储空间。一般会在内存中创建相应的数据结构,但这种情况下,系统一旦掉电,所有的会话数据就会丢失,如果是电子商务网站,这种事故会造成严重的后果。不过也可以写到文件里甚至存储在数据库中,这样虽然会增加I/O开销,但session可以实现某种程度的持久化,而且更有利于session的共享;
将session的全局唯一标示符发送给客户端。 问题的关键就在服务端如何发送这个session的唯一标识上。联系到HTTP协议,数据无非可以放到请求行、头域或Body里,基于此,一般来说会有两种常用的方式:cookie和URL重写。
Cookie是如何被设置的呢?是被服务器返回的请求设置的。
服务器会返回一个set-cookie的消息,通知浏览器要设置cookie了,于是浏览器会根据set-cookie里的字段来设置信息了.
const port = 3000;
const hostName = '127.0.0.1';
const http = require('http')
const fs = require('fs')
const url = require('url');
const server = http.createServer((req, res)=>{
// 接收POST请求
let data = ""
if (req.method === 'POST') {
const { query, pathname } = url.parse(req.url, true);
if (pathname == "/post/userInfo") {
req.on('data', chunk => {
// 拼接数据
data += (chunk);
})
req.on('end', () => {
data = JSON.parse(data)
console.log(data)
})
}
}
}.listen(port, hostName, () => {
console.log(`服务器已启动:${hostName}:${port}`)
})
// 接收GET请求
server.on('request', (requset, response) => {
const { query, pathname } = url.parse(requset.url, true);
// 这里使用JSON.stringify(query)和JSON.parse(data)进行转换为对象 防止出现 [Object: null prototype] 的警告
let data = JSON.stringify(query);
data = JSON.parse(data);
response.writeHead(200, { 'Content-type': 'text/plain' });
response.end('服务器已接收GET请求')
})
// 用于生成UUID
const crypto = require('crypto');
// 生成UUID
const uuid = crypto.randomUUID();
邮箱验证码思路
验证码发送阶段
客户端上传邮箱地址到服务端,服务端通过生成随机验证码,并将这个验证码发送到用户上传的这个邮箱中。此时服务端需要将这个邮箱和验证码保存到数据库的某张表中(后文中使用Code来称呼这个表),同时保证这条记录的唯一性。并在有效时间内将这条记录删除(此时间就是验证码的有效时间)
验证码验证阶段
客户端将收到的验证码和邮箱重新发送到服务端,服务端开始验证:
是否能够从Code中查询到这条验证码和邮箱与客户端发送一致的记录 是:验证通过,并删除这条记录 否:验证不通过 验证码发送阶段 ————————————————
// express 框架生成器
npx express-generator
// 安装express
npm install express
// 安装自动更新包
npm install nodemon
// 基本使用
const express = require('express')
const app = express()
// 静态文件中间件
const path = require('path')
app.use(express.static('public'))
app.use('/static', express.static(path.join(__dirname, 'public')))
// 全局中间件
const myLogger = function(req, res, next){
console.log('log')
next()
}
// 根据路由接收请求
app.get('/', (req, res)=>{
res.send('hello world!')
})
// 局部中间件
app.post('/', function(req, res, next){
console.log("执行了局部中间件")
next()
},(req, res)=>{
res.send('hello world!')
})
app.put('/user', (req, res)=>{
res.send('hello world!')
})
// 无匹配请求地址处理
app.all('*', (req, res, next)=>{
res.send("找不到改请求地址")
next()
})
// 服务器请求的异常处理
app.use((err, req, res, next)=>{
console.log(err.stack)
res.status(500).send("服务器出错")
})
app.listen(port, ()=>{
console.log(`server is runing, port:${port}`)
})
// express 的模板引擎
// 设置模板文件夹和模板引擎
app.set('views', __dirname+"/views")
app.set('view engine', 'ejs')
var indexRouter = require('./routes/index')
app.get('/user', indexRouter)
// 下列代码为routes/index.js路由文件中的代码
router.get('/', function(req, res){
//调用模板解析引擎渲染页面,名为index的模板并传入一个对象为参数
res.render('index', {title: 'Express'})
})
module.exports = router
1.后端已设置允许跨域,使用Express传递携带session的cookie给前端,在响应体的set-cookie
里面有值,但前端没有存储cookie同时在Application中并没有存储cookie值。
2.原因是前端没有设置允许跨域传递cookie,给xhr
的属性withCredentials
赋值为true即可。
1.后端允许跨域
app.use((req, res, next)=>{
// 设置允许跨域的域名
res.set('Access-Control-Allow-Origin', req.headers.origin);
res.set('Access-Control-Allow-Methods', '*');
res.set('Access-Control-Allow-headers', '*');
res.set('Access-Control-Allow-Max-age', '*');
// 允许跨域传递cookie
res.set('Access-Control-Allow-Credentials', true);
next();
})
cookie由键值对字符串组成, 在设置Cookie时,可以指定以下属性:
对document.cookie
重新赋值即可新增该Cookie
, 而不是替换掉整个Cookies
。
注意:如果需要替换某个Cookie
, 必须保证Domain
与Path
一致。其中 Cookie 内容只能包括 Ascii 码字符,所以需要经过一层编码。
// 设置后端响应头
// 设定运行访问的源(域,协议,端口)
response.setHeader('Access-Control-Allow-Origin', '*');
// 设定运行访问的方法
response.setHeader('Access-Control-Allow-Methods', '*');
// 设定运行访问的自定义请求头
response.setHeader('Access-Control-Allow-headers', '*');
// 是否允许携带身份凭证
response.setHeader('Access-Control-Allow-Credentials', '*');
// 指定预检请求的缓存时间
response.setHeader('Access-Control-Allow-Max-age', '*');