华清远见重庆中心--node.js阶段学习总结

一、Node.js 基础

1.Node.js 是什么

  • 不是一门语言,不是库,不是框架
  • 是一个JavaScript运行时环境,简单点说就是node.js可以解析和执行- -JavaScript代码
  • nodejs使用JavaScript语言编程,运行在JavaScript引擎上(V8)
  • node.js为JavaScript提供了许多服务器级别的操作API(http,fs等)
  • node.js包含EcmaScript,但是不包含DOM,BOM,编码方法同JavaScript
  • node.js是一个基于 Chrome浏览器 V8 引擎的 JavaScript 运行时(环境)
  • node可以理解为是nodejs的作者基于Chrome浏览器的V8引擎,使用- - - - JavaScript开发的一个平台(环境),所以node可以解析和执行JavaScript代码
  • Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台
  • Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

2.Node.js 安装

Node.js 安装教程:Node.js 安装配置 | 菜鸟教程

Node.js 安装注意:

  • Node.js 的安装直接前往官网安装即可,根据需求选择版本
  • 配置环境变量
  • 设置npm安装程序时的默认位置,和缓存位置
npm config set prefix "D:\nodejs\X64\node_global"  //默认位置

npm config set cache "D:\nodejs\X64\node_cache" //缓存位置
注:先在相应的位置建立文件node_global和node_cache,再设置
  • 设置环境变量NODE_PATH
NODE_PATH = D:\nodejs\X64\node_global\node_modules
(很重要,尤其是全局安装node插件时),否则会出现XXX不是内部命令的错误。

3.Node.js 特性

  • 单线程

在Java,PHP或者.net语言中,会为每一个客户端连接创建一个新的程,而每个线程需要耗费大约2MB内存,所以就会限制同时连接的用户数量。Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程,当有用户连接了就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Nodejs程序宏观上也是并行的,大大提高用户的连接数量(性能)。

  • 非阻塞IO模型(IO指 input output 输入 输出)

当在访问数据库取得数据的时候,需要一段时间,在传统的单线程处理制中,在执行了访问数据库代码之后,整个线程都 将暂停下来,等待数据库返回结果,才能执行后面的代码,也就是说,I /O阻塞了代码的执行,极大的降低了程序的执行效率,而Nodejs中采用了非阻塞型I / O机制,因此在执行访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回的结果处理代码放在回调函数中,从而提高了程序的执行效率,当某个I / O执行完毕时,将以事件的形式通知执行I / O操作的线程,线程执行这个事件的回调函数,为了处理异步I /O,线程必须有事件循环,不断的检查有没有未处理的 事件,依次予以处理。阻塞模式下,一个线程只能处理一项任务,想要提高吞吐量必须通过多线程,而非阻塞模式下,一个线程永远在执行计算操作这个线程的CPU核心利用率永远是100%。

  • 事件驱动

在Nodejs中,客户端请求建立连接,提交数据等行为,会触发相应的事件。在Node中,在一个时刻,只能执行一个事件回调函数,但是在执行一个事件回调函数的中途,可以转而处理其他事件(比如,又有新用户连了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。

  • 轻量和高效
  • 没有全局作用域

只有模块作用域,所以不能进行像JavaScript那样的变量等的访问、调用操作Nodejs中没有根目录(目录)的概念,因为它没有任何的web容器(可以理解成相当于一个服务器,如Apache/Tomcat)

4.Node.js的简单使用

(1) 、命令终端

  • Node.js的全局对象是 global ; javascript的全局对象是 window
  • 直接在命令终端中输入node,然后回车,就会出现 ‘>’ 标识,然后就可以写js语法了
  • 命令终端退出: Ctrl + c 两次

(2) 、文件型使用

  • 命令行键盘 tab 键 自动补全文件名称
  • 执行文件/运行文件:
$ node 文件名称.js

二、NPM

1.NPM是什么

NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:

  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

注:

输入 “npm -v” 来测试是否成功安装

2.NPM使用

(1)、使用淘宝镜像的命令

大家都知道国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。

淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。

你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

 npm install -g cnpm --registry=https://registry.npm.taobao.org

这样就可以使用 cnpm 命令来安装模块了:

cnpm install [name]

(2)、npm 命令安装模块

npm 安装 Node.js 模块语法格式如下:

npm install <Module Name>

以下实例,我们使用 npm 命令安装常用的 Node.js web框架模块 express:

 npm install express

express 包就放在了工程目录下的 node_modules 目录中

因此在代码中只需要通过 require(‘express’) 的方式引用就好,无需指定第三方包路径。

var express = require('express');

(3)、全局安装与本地安装

npm 的包安装分为本地安装(local)、全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已,比如

npm install express          # 本地安装
npm install express -g   # 全局安装

本地安装:

  • 将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。
  • 可以通过 require() 来引入本地安装的包。

全局安装:

  • 将安装包放在 /usr/local 下或者你 node 的安装目录。
  • 可以直接在命令行里使用。

(4)、查看安装信息

可以使用以下命令来查看所有全局安装的模块:

npm list -g

(5)、 package.json

Package.json 属性说明:

  • name - 包名。

  • version - 包的版本号。

  • description - 包的描述。

  • homepage - 包的官网 url 。

  • author - 包的作者姓名。

  • contributors - 包的其他贡献者姓名。

  • dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。

  • repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。

  • main - main 字段指定了程序的主入口文件,require(‘moduleName’) 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。

  • keywords - 关键字

(6)、卸载模块

卸载 Node.js 模块:

npm uninstall express

卸载后,你可以到 /node_modules/ 目录下查看包是否还存在,或者使用以下命令查看:

npm ls

(7)、更新模块

我们可以使用以下命令更新模块:

npm update express

(8)、搜索模块

使用以下来搜索模块:

npm search express

(9)、创建模块

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
 
See `npm help json` for definitive documentation on these fields
and exactly what they do.
 
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
 
Press ^C at any time to quit.
name: (node_modules) runoob                   # 模块名
version: (1.0.0) 
description: Node.js 测试模块(www.runoob.com)  # 描述
entry point: (index.js) 
test command: make test
git repository: https://github.com/runoob/runoob.git  # Github 地址
keywords: 
author: 
license: (ISC) 
About to write to ……/node_modules/package.json:      # 生成地址
 
{
  "name": "runoob",
  "version": "1.0.0",
  "description": "Node.js 测试模块(www.runoob.com)",
  ……
}
 
 
Is this ok? (yes) yes

可以使用以下命令在 npm 资源库中注册用户(使用邮箱注册):

$ npm adduser
Username: mcmohd
Password:
Email: (this IS public) mcmohd@gmail.com

接下来我们就用以下命令来发布模块:

npm publish

(10)、NPM 常用命令

NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。

  • 使用npm help 可查看某条命令的详细帮助,例如npm help install。

  • 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。

  • 使用npm update 可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。

  • 使用npm update -g可以把全局安装的对应命令行程序更新至最新版。

  • 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。

  • 使用npm unpublish @可以撤销发布自己发布过的某个版本代码

三、Node.js扩展

1.Node.js REPL

  • Node 自带了交互式解释器,可以执行以下任务:

  • 读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。

  • 执行 - 执行输入的数据结构

  • 打印 - 输出结果

  • 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

(1)、REPL 命令

  • ctrl + c - 退出当前终端。

  • ctrl + c 按下两次 - 退出 Node REPL。

  • ctrl + d - 退出 Node REPL.

  • 向上/向下 键 - 查看输入的历史命令

  • tab 键 - 列出当前命令

  • .help - 列出使用命令

  • .break - 退出多行表达式

  • .clear - 退出多行表达式

  • .save filename - 保存当前的 Node REPL 会话到指定文件

  • .load filename - 载入当前 Node REPL 会话的文件内容。

(2)、停止 REPL

按下两次 ctrl + c 键就能退出 REPL:

$ node
>
(^C again to quit)
>

2.require详解

nodejs中require使用非常频繁,或者说在模块化开发中起到非常重要的作用

使用通常类似这样:

var fs = require('fs')
const http = require('http')

可是你真的了解它吗?在node中require方法有两个作用:

  1. 加载文件模块并执行里面的代码
  2. 拿到被加载文件模块导出的接口对象 (exports)

3.文件系统

FileSystem,文件系统,样例:

// 引入fs模块
const fs = require('fs')
// 读文件
fs.readFile('./我的生词本.txt', function (err, data) {
  console.log(data.toString())
  console.log(err)
})
// 写文件
fs.writeFile('./writeFile.txt', '大家好,我是帅哥!', function (err) {
  console.log('文件写入成功')
  console.log(err)
})

4.http

使用http API可以快速的创建一个服务器

// 引入http模块
const http = require('http')
// 创建一个web服务器(使用createServe方法,返回一个Serve实例)
var serve = http.createServer();
// 注册 request 请求事件(当客户端发请求过来就会自动触发 request 请求事件,执行回调函数)
// 回调函数接收两个参数,request,response
// request是客户端发送的请求信息
// response有一个write方法,可以用来向客户端发送响应信息
serve.on('request', function (request, response) {
  console.log('客户端请求发送成功')
  // console.log(request)
  response.writeHead(200, { 'Content-Type': 'text/plain;charset=UTF8' })// 设置响应头
  response.write('这是服务端向客户端响应的内容~~~')
  response.write('nodejs')
  // 通过response.end方法结束响应,告诉客户端,服务端响应完毕
  response.end()
})
// 绑定端口号,启动服务器
serve.listen('5000', function () {
  console.log('服务器启动成功了~')
})
// 创建一个服务,并加载html文件,展示页面
var http=require("http");
var fs=require("fs"); //导入文件模块
var server =http.createServer(function(req,res){
    //设置头信息
    res.setHeader("Content-Type","text/html;charset='utf-8'");
    //读文件
     fs.readFile("./index.html","utf-8",function(err,data){
         if(err) {
           console.log("index.html loading is failed :"+err);
         } else {
           //返回index.html页面
           res.end(data);
         }
     });
}).listen(8888); //监听端口,注:一个程序只能监听一个端口

5.path

path模块提供了一些用于处理文件与目录的路径的实用工具。

最常用的resolve方法:

// path
const path = require('path')
// 使用如:
index: path.resolve(__dirname, '../dist/index.html'),
// path.resolve() 方法将路径或路径片段的序列解析为绝对路径,
// 给定的路径序列从右到左进行处理,每个后续的 path 前置,直到构造出一个绝对路径
// 如果任何参数不是字符串,则抛出 TypeError

Node.js中提供了两个与文件操作相关全局可用变量__dirname和__filename,__dirname表示当前文件所在的目录,__filename表示正在执行脚本的文件名。

6.express框架

express是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。

原生的node开发存在很多问题:

  • 呈递静态页面很不方便,需要处理每个http请求,还要处理304问题
  • 路由处理代码不直观清晰,需要很多正则表达式和字符串函数
  • 不能集中精力写业务,要考虑很多其他的东西

所以express框架应运而生:

  • express框架有着惊艳的路由能力,正则提取数据能力足够一般工作使用
  • express中的静态文件处理就是一句话的事
  • express与模板引擎的配合更直观清晰

Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。

  • 定义了路由表用于执行不同的 HTTP 请求动作。

  • 可以通过向模板传递参数来动态渲染 HTML 页面。

安装 Express 并将其保存到依赖列表中:

$ cnpm install express --save

以上命令会将 Express 框架安装在当前目录的 node_modules 目录中, node_modules 目录下会自动创建 express 目录。以下几个重要的模块是需要与 express 框架一起安装的:

  • body-parser - node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。

  • cookie-parser - 这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象。

  • multer - node.js 中间件,用于处理 enctype=“multipart/form-data”(设置表单的MIME编码)的表单数据。

$ cnpm install body-parser --save
$ cnpm install cookie-parser --save
$ cnpm install multer --save

Express 框架实例

//express_demo.js 文件
var express = require('express');
var app = express();
 
app.get('/', function (req, res) {
   res.send('Hello World');
})
 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})
 
//输出 "Hello World"

7websocket 简介

websocket 是一个服务器和客户端双向通信的协议(双工通道),主要用作服务器向客户端主动推送数据。

websocket api

express 服务器也可以实现 websocket 协议,可以使用 express-ws

websocket 更常见的使用方法是做一个独立服务器,如直播弹幕服务器,聊天服务器等

完成上述服务器的 node.js 的框架有 socket.io

const express = require('express');
const path = require("path");
const app = express();
// 引入 express-ws 包 并安装到 app 对象上
const expressWs = require('express-ws')(app)


app.use('/', express.static(path.join(__dirname, 'public')))


// 使用 app.ws 开一个 ws 协议的接口
// 用于接收和发送数据
app.ws('/', (ws, req) => {
    // ws 代表一个连接,是一个通信的数据通道

    // 给连接绑定消息事件,这样的话当客户端发送消息的时候服务器就会触发此处的回调函数
    ws.on('message', (msg) => {
        console.log(msg)
        // 服务器返回一句话作为响应
        ws.send('server receive message: ' + msg)
    })
})

// 用于存储连接的对象
const wsMap = {}
// 自增id
let id = 0

// 聊天连接
app.ws('/chat', (ws, req) => {
    ws.on('message', (msg) => {
        // 反序列化数据对象
        msg = JSON.parse(msg)
        switch (msg.type) {
            case 'login':
                // 存储连接
                wsMap[msg.data] = ws
                // 分配id
                ws.id = id++
                wsMap[ws.id] = msg.data
                ws.send('连接成功')
                break;
            case 'send':
                // 读取要发送数据的连接
                // 找到消息接收人
                let _ws = wsMap[msg.data.receiver]
                // 获取发送人的名字
                let sender = wsMap[ws.id]
                // 发送消息
                _ws.send(`${sender}: ${msg.data.message}`)
                break;
        }
    })
})

app.listen(80, () => {
    console.log('server start on: http://127.0.0.1')
})

html页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
</head>
<body>
<div>昵称: <input class="name" type="text">
    <button onclick="connect()">连接</button>
</div>
<div>
    <div>接收人: <input class="receiver" type="text"></div>
    <div>消息: <input class="message" type="text"></div>
    <button onclick="send()">发送</button>
</div>
</body>
<script>
    const nameInp = document.querySelector('.name')
    const receiverInp = document.querySelector('.receiver')
    const messageInp = document.querySelector('.message')

    let socket

    // 创建连接
    function connect() {
        socket = new WebSocket('ws://127.0.0.1/chat')
        socket.addEventListener('open', () => {
            // 当连接建立成功后向服务器表明身份
            socket.send(JSON.stringify({type: 'login', data: nameInp.value.trim()}))
        })

        socket.addEventListener('message', ev => {
            console.log(ev.data)
            // 显示消息
            let p = document.createElement('p')
            p.textContent = ev.data
            document.body.appendChild(p)
        })
    }

    // 发送数据
    function send() {
        socket.send(JSON.stringify({
            type: 'send',
            data: {receiver: receiverInp.value.trim(), message: messageInp.value}
        }))
    }
</script>
</html>```
## 跨域处理
当客户端请求的url域和服务器所在的域不同时,会触发浏览器的安全机制,限制跨域访问,此时服务器需要打开跨域访问的许可,允许跨域。在express中,需要在服务器启动前,安装如下代码:
```js
// 设置允许跨域访问该服务.
app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    // Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    // res.header('Content-Type', 'application/json;charset=utf-8');
    next();
})

跨域例子:例如:

  • 服务器地址是:shampoo6.com,有一个接口 /game/info
  • 另一个页面,地址是:cat.com/index.html
  • 当 cat.com/index.html 页面访问 shampoo6.com/game/info 接口时,由于域名不同,这就产生了跨域
  • 如果 shampoo6.com 服务器不做跨域处理,就会报如下错误:
Access to XMLHttpRequest at 'http://shampoo6.com/game/info' from origin 'cat.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

8.跨域处理

当客户端请求的url域和服务器所在的域不同时,会触发浏览器的安全机制,限制跨域访问,此时服务器需要打开跨域访问的许可,允许跨域。在express中,需要在服务器启动前,安装如下代码:

// 设置允许跨域访问该服务.
app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    // Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    // res.header('Content-Type', 'application/json;charset=utf-8');
    next();
})

跨域例子:例如:

  • 服务器地址是:shampoo6.com,有一个接口 /game/info
  • 另一个页面,地址是:cat.com/index.html
  • 当 cat.com/index.html 页面访问 shampoo6.com/game/info 接口时,由于域名不同,这就产生了跨域
  • 如果 shampoo6.com 服务器不做跨域处理,就会报如下错误:
Access to XMLHttpRequest at 'http://shampoo6.com/game/info' from origin 'cat.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

9.使用 cors 模块进行跨域

安装 cors

npm i cors

使用如下:

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

// 跨域处理可以放在所有中间件的前面
app.use(cors())

10.中间件

中间件middleware,是一个采用责任链模式夹杂在我们的服务器方法中间的方法。

作用:在访问指定接口之前或之后的一个自定义方法,就是中间件

特点:

  • 既然叫中间件,它是可以夹在方法中间的
  • 责任链:这是个设计模式,调用到自己方法时,如符合处理条件,就自行处理并终止操作,否则就传递给下一个处理程序。
  • 方法(function):中间件依然是个方法
  • 有序:中间件代码是有顺序的,放的位置不一样,调用时机就不同

语法:

app.use((req, res, next)=>{
    // 中间件逻辑
    next()
})
// 或
router.use((req, res, next)=>{
    // 中间件逻辑
    next(someParams)
})

方法签名最后一个参数一定是 next,且调用next就执行下一个方法,否则就需要在此处res.end否则程序会挂起

next方法调用时,可以接受一个Error对象作为参数,用作抛出异常,任何异常将在下一个中间件的第一个参数中获得,接下来的异常处理就会用到

(1)中间件的作用

  1. 充当请求的拦截器
  2. 异常处理

(2)异常处理

异常处理在实际项目中非常常见,因为通常程序除了异常,服务器都需要一个统一的返回数据让页面显示,为了更友好,更好看,且数据格式需要在异常处理的时候格式化成需要的数据格式。

// 自定义返回结构
let result = {
    code: 0000 // 业务码
    msg: '业务成功',
    result: {}
}

异常处理的方式就是使用中间件,中间件的位置需要在所有请求和中间件之后书写。如:

app.use((req, res, next)=>{
    console.log('this is middleware')
    next()
})

app.get('/', (req, res, next) => {
    // 接口内也能接收一个 next
    // next 函数用于接口抛出异常给后续中间件
    // console.log('this is /')
    // res.end('hello home!')
    next(new Error('my error'))
})

// 定义异常处理器
app.use((err, req, res, next)=>{
    console.log(err)
    res.status(500)
    res.end(err.stack)
})

异常处理器的方法签名中,第一个参数,始终是error,如果程序没有抛错的话,那么错误处理程序将不会被调用

异常分类与处理

异常通常分为两类:系统异常,业务异常

  • 系统异常:通常由于开发人员的bug导致,这种异常不应该让用户看见,所以处理的时候通常会返回:"服务器忙,请稍后再试"等友好的提示语句。
  • 业务异常:设计某一个具体功能,由于用户操作导致的异常。如:登录的时候密码不对,邮箱格式不正确,用户的非法输入和不和逻辑的操作都是业务异常。此类异常通常需要告知用户,用户哪里做错了来作为提示。

这两种异常怎么处理呢?通常我们不会去修改http的status code,也就是http协议的状态码。而是服务器规定一组错误码,前端解析或服务器直接返回错误提示,如下:

先判断异常是系统异常还是业务异常,这里我们需要先定义一个我们自己的异常类,如下:

class MyError extends Error {

}

module.exports = {MyError}

然后在业务逻辑出错时,我们应该主动抛出自定义异常,如下

const {MyError} = require('./myError')

app.post('/user/login', (req, res)=>{
    // 这里如果说,我们判断到用户密码不对,那么需要抛出一个业务异常
    throw new MyError('登录密码不正确')
})

在异常抛出后,我们需要一个异常处理逻辑来处理异常:

app.use((err, req, res, next)=>{
    if (err instanceof MyError) {
        // 在这里做业务异常处理的事情
        res.end(err.message)
    } else {
        // 在这里做系统异常处理的事情
        res.end('this is not myError')
    }
})
总结

异常处理中间件可以捕获以下异常:

  1. 在接口回调函数中抛出的异常,如:throw new Error('my error')
  2. 在接口回调函数中使用 next 函数抛出的异常,如: (req, res, next)=>{ next(new Error('my error')) }

异常处理中间件无法捕获的内容如下:

  1. promise 中 reject 的异常
  2. 若接口回调是一个异步函数,也无法捕获

处理上述无法捕获异常的方法如下:

  1. 安装 express-async-handler

  2. 给接口回调函数包装一层 asyncHandler

    const asyncHandler = require('express-async-handler');
    app.get('/asyncHandler', asyncHandler(async (req, res) => {
        await Promise.reject('my error');
        res.json({code: 200, msg: 'promise 调用成功', result: null});
    }));
    

11.cookie

什么是cookie?

浏览器用于存储指定url请求下的参数的工具,就是cookie,是浏览器的状态管理工具

cookie有哪些作用
  • 存储指定url路径下的参数,以 { key: value } 键值对的形式存储
  • 设置数据失效时间,时间到后会自动失效
  • 每次浏览器发起请求时,如果请求地址保存有cookie,那么浏览器会自动将cookie的值传给服务器
    总的来说,cookie就是浏览器用来储存本地数据的
安装cookie工具
npm install cookie-parser

配置

const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()

app.use(cookieParser())
cookie的读写
app.get('/', (req, res) => {
    // 读取cookie
    console.log(req.cookies)
    // 写入cookie
    // httpOnly: 只能在http协议中使用
    // maxAge: 有效时间
    res.cookie('a', '123', {httpOnly: true, maxAge: 3000})
    res.end('hello world')
})
cookie的路径

我们可以通过cookie.setPath来修改路径,路径存在以下注意点:

  • /web05/xx/add — 添加了cookie
  • /web05/xx — 找不到在“add”路径上,添加的cookie
  • /web05/xx/add/abc — 可以找到“add”路径上,添加的cookie
  • cookie.setPath(“url”) , 修改cookie的添加路径
    response.addCookie(cookie) – 添加cookie, 如果没有使用cookie.setPath(“url”)方式,修改cookie的添加路径,那么cookie的路径就是当前的url地址。
cookie的限制
  • 用户可以禁止cookie
  • 用户可以删除cookie
  • cookie不安全
  • cookie能存储的数据小于4k
  • cookie个数不能超过300个
  • cookie的数据只能是字符串
  • cookie不能存中文

要让cookie存储中文,需要对内容进行url编码

12.session理论

什么是session

session是客户端链接服务器的一个会话,当创建与服务器的链接时,session由服务器创建,用于描述服务器状态的对象

有什么用?

用于多次请求之间能够共享数据

session的原理
  • 浏览器访问服务器到时候,服务器会创建一个session对象(每一个session对象,都会有一个唯一标志-sessionId)
  • 默认情况下sessionId会保存在浏览器中的cookie中,再次访问这个服务器的时候,浏览器会将cookie中的sessionId发送到服务器,服务器可以根据sessionId找到session对象
安装session工具
npm i express-session

配置

const express = require('express')
const session = require('express-session')
const app = express()
const port = 1024

// 配置session
app.use(session({
    secret: 'this is a secret key', // 必要参数 这是一个签名密钥
    cookie: ('name', 'value', {})
    // cookie: ('name', 'value', {maxAge: 5*60*1000, secure: false})
}))
session操作
app.get('/', (req, res) => {
    // 读取session
    console.log(req.session)
    // 写入session
    if (req.session.count)
        req.session.count = req.session.count + 1
    else
        req.session.count = 1
    res.end('hello world')
})
session特点
  • session对象, 浏览器关闭之后,session对象消失。
  • session,默认情况下,30分钟,都不再和服务器端有交互,则session无效。
  • session可以实现服务器端数据的共享(临时数据)
  • session保存的数据在服务器内存中
  • 更换客户端,session就找不到了
  • 由于session是存在内存中,多台服务器的项目就不能有效访问session
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

埃菲尔上de铁塔梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值