为了账号安全,请及时绑定邮箱和手机立即绑定

node.js笔记

2018.10.16 20:40 2107浏览

node.js 介绍

node.js是什么

  1. node.js 是一个开发平台,就像java开发平台...

  • 何为开发平台? 有对应的编程语言,有语言运行时,有能实现特定功能的API

该平台使用的编程语言是 javascript 语言

node.js 平台是基于 v8 引擎构建

基于node.js可以开发控制台程序(命令行程序,CLI程序),桌面应用程序(GUI)(借助node-webkit等框架实现),web应用程序(网站)

php开发技术栈: LAMP - Linux Apache MySQL PHP

node.js 全栈开发技术栈: MEAN - MongoDB Express Angular Node.js

node.js 有哪些特点?

  1. 事件驱动

  2. 非阻塞 I/O 模型

  3. 单线程

  4. 拥有世界最大的开源库生态系统 -- npm

node.js 安装和配置

  1. 官方解释

  • LTS 版本: 稳定版

  • current版本: 最新版本

  1. 注意

  • 配置环境变量:

  1. 通过 nvm-windows 控制管理 node多个版本

node.js 开发web程序和 php,java,asp.net 等传统模式开发web应用程序区别

  1. 传统模式

  • 有web容器

  1. node.js

  • 没有web容器

在node.js 上编写程序

REPL介绍

  1. REPL 全称 read eval print loop (交互式解释器)
    R 读取
    E 执行
    P 打印
    L 循环

  2. 在REPL中编写程序(类似于F12 console控制台)

  • 直接在控制台输入 node 命令进入REPL环境

  1. 按两次ctrl+c 退出REPL 或者 输入 .exit

fs

读取文件

var fs = require('fs')

fs.readFile('路径',(err,data)=>{    if(err) throw err;
    cl(data.toString('utf-8'))
})

__dirname和__filename获取正在执行的js文件路径

这两个东西, 不算是全局的 相当于本地的 会在当前js中产生一个闭包吧他们传进去

path

通过path模块进行路径拼接

path.join(__dirname,'hello.txt');

error-first介绍(错误优先)

http模块

见: 搭建一个简单的http服务程序.js

通过服务区端设置响应报文头来解决乱码问题

response.setHeader('Content-Type','text/plain; charset=utf-8');

http响应报文头 作用 告诉浏览器发送数据的其他相关信息

根据不同请求做出不同的响应

response.setHeader('Content-Type','text/html; charset=utf-8');

try-catch 的使用

异步操作, try-catch是无法捕获异常的

对于异步操作, 要通过判断错误号(err.code)来进行出错出处理

npm模块 mime

通过mime 可以根据后缀 得到mime type

在请求服务器的时候, 请求的 url 就是一个标识

res对象

  • res.write()

  • res.end()    结束响应(请求)

  • res.setHeader('Content-Type': 'text/html')  设置响应报文头

  • res.statusCode = 404; 设置 http 响应状态码

  • res.statusMessage = 'Not Found'; 设置 http 响应状态码对于信息

  • res.writeHead()  直接向客户端响应(写入)响应报文头

     res.writeHead(404,'Not Found',{     'Content-Type': 'text/html'
     })

res.setHeader方法 和 res.writeHead方法 区别

npm (node package manager) node包管理器

npm 和 node.js

  • npm本身也是基于node.js开发的包

如何安装npm

  • npm会随着node.js自动安装

  • 查看npm版本: npm -v

  • 更新npm: npm install npm@latest -g

npm使用

  1. 在网站找到需要的包

  2. 在项目根目录下 执行 npm install 包名 安装

  3. 在node.js代码中通过 `require('包名') 加载该模块

---- 本地安装

npm全局安装介绍

npm install mime -gmime a.txt

安装完毕后可以在命令行中直接使用(本质)

npm全局安装世纪做了两件事:

  1. 下载包到指定目录

  2. 创建一段命令行执行代码

package.json 文件(包说明文件)

元数据: 描述自身的数据

如何创建

  1. 通过npm init或者npm init -y或者npm init -yes命令

  2. 手动创建

注意

  1. 创建时,执行命令所在目录名称不能包含大写字母和中文

package-lock.json 文件

记录了要安装包的所有信息 可以加快安装速度

DAY 3

路由组成: 请求方法 请求路径

url模块 parse方法 获取get提交数据

str.startwith('xx') //字符串方法  以xx开头 返回boolean

const url = require('url');const urlObj = url.parse(req.url, true); // 返回包含url所有内容的对象  第二个参数为true 可以让urlObj.jquery内容转为json对象

req.query 获取? 后面的数据

restful形式的接口

服务器想让浏览器做什么事情 通过传递响应报文头来实现

underscore 工具函数库

const _ = require('underscore');

_.zipconst html = '<%= name %>';const fn = _.template(html)
html = fn({name:'哈哈'}) // 哈哈

DAY 4

封装异步代码 需要一个回调函数

nodejs中模块

一. nodejs中模块的分类

1.核心模块, 内置模块, 原生模块

2.文件模块

如果加载时没有指定后缀名,name按照如下顺序依次加载响应模块

  1. .js

  2. .json

  3. .node

  4. 文件夹 -> package.json -> main (入口文件 app.js 没有的话-> index.js/index.json/index.node) -> 加载失败

注意:文件模块加载 最好带后缀名

3.自定义模块

  1. mime

  2. moment

  3. ...

情况一: require() 参数是一个路径

  1. .js

  2. .json

  3. .node

  4. 文件夹 -> package.json -> main (入口文件 app.js 没有的话-> index.js/index.json/index.node) -> 加载失败

情况二: require() 参数是一个模块名称

  • 核心模块: 直接加载

  • 不是核心模块: 会在当前文件夹找 node_module

    • 从当前目录开始,依次地魁查找所有父目录中的node_module 目录中是否有相应的包

    • 如果查找完毕 磁盘根目录依然没有则加载失败

    • 打印数据 module.paths 查看

    • 依次递归查找 node_module 目录中是否有相应的包

Common JS 规范

总结: commonJS 是为JavaScript 语言判定的一种  模块规范, 编程 API规范

exports 和 module.exports 区别

  • exports 和 module.exports 都指向的是用一个对象

  • 最终 require() 函数返回的是 module.exports 中的数据

  • exports 仅仅是一个 快捷方式

webp

exports 和 module.exports 区别

模块化思路

  • 该模块要封装什么代码

  • 这些代码有用到外部数据吗? 如果用到,是否需要通过参数传递到当前模块中

  • 当前模块要暴露的东路(module.exports 的值)

DAY 5

Buffer

一. 类型介绍

  1. javascript 语言没有读取或操作二进制数据流的机制

  2. Node.js中引入 Buffer类型使我们可以操作TCP流或文件流

  3. Buffer类型的对象类似于整数数组, 但大小是固定的(buf.length是固定的,不允许修改)

  4. Buffer是全局的,所以使用的时候无需require()的 方式来加载

二. 创建一个Buffer对象

var buf = Buffer.from('你好!');console.log(buf);console.log(buf.toString('utf8'));

三. Buffer 对象与编码

node.js目前支持的编码:

  1. ascii

  2. utf8

  3. base64

  4. ...


使用 nodemon 工具来自动重启web服务器

  • nodemon的作用:能够实时监听当前项目中,文件的变化;只要监听到了文件的变化,则 nodemon 工具,会自动重新启动 web 服务器,从而使最新的代码生效;免去了程序员手动重启服务器的困扰;

  • 如何安装:运行 npm i nodemon -g  全局安装即可;

  • 如何使用:

    • 之前使用 node 要执行的文件路径 来运行 Node.js 代码;

    • 现在使用 nodemon 要执行的文件路径 来运行 Node.js 代码;

  • 注意:今后在开发Web项目的时候,推荐使用 nodemon 来启动 web 服务器

express (Node 中开发web项目的框架)

定义(什么是Express):一个快速的网站开发框架,封装了原生的http模块,用起来更方便;API更人性化

什么是express

  • 基于 node.js平台开发的 'web开发框架',就是一个node.js模块

  • 作用: 提供一系列强大的特性,帮助你创建各种web和移动设备的应用

特点

  1. 实现了路由功能

  2. 中间件(函数)功能

  3. 对req,res对象的扩展

  4. 可以集成其他模板引擎

express 框架的安装和基本使用

  1. 安装:运行 npm i express -S 即可安装

  2. 创建基本的 express 服务器:

  • 监听 GET 请求:app.get('请求地址', (req, res) => { 处理函数 })

  • 监听 POST 请求: app.post('请求地址', (req, res) => { 处理函数 })

  • 导入 express 第三方模块;

  • 创建服务器的实例:调用 const app = express() 方法;

  • 通过 app.get()app.post() 方法,来监听客户端的 getpost 请求,具体语法:

  • 启动 express 服务器:通过 app.listen(端口, IP地址, 启动成功后的回调函数) 启动服务器;

express 中的快捷方法

  1. res.send()

    1. 支持 发送 字符串 Content-Type: text/html;

    2. 支持 发送 对象 或 数组 Content-Type: application/json

    3. 支持 发送 Buffer 此时会当作文件下载;

  2. res.sendFile()

  • 用法1:res.sendFile(path.join(__dirname, './view/index.html'))

  • 用法2:res.sendFile('./view/movie.html', { root: __dirname })

  • 注意:res.sendFile() 可以向浏览器发送 静态页面;

res.send()和res.end()区别

  • res.end()用于快速响应,没有数据返回到客户端

  • res.send()有数据返回到客户端

res对象的常见方法

res.json() 等价于 res.send(json)

res.sendFile() 读取文件并响应

res.redirect() 重定向

res.status(404).end('文件不存在')

使用 express.static() 快速托管静态资源

如果我们网站中,有很多静态资源需要被外界访问,此时,使用 res.sendFile 就有点力不从心了;

这时候,express 框架,为我们提供了 express.static('静态资源目录')

来快速托管指定目录下的所有静态资源文件;

  1. 语法1: app.use(express.static('public'));

  • app.use()方法,是专门用来注册 中间件;

  • express.static 是express的内置中间件;

语法2:app.use('/虚拟目录', express.static('public'))

为 express 框架配置 ejs模板引擎 渲染动态页面

  1. 安装 ejs 模板引擎npm i ejs -S

  2. 使用 app.set() 配置默认的模板引擎 app.set('view engine', 'ejs')

  3. 使用 app.set() 配置默认模板页面的存放路径 app.set('views', './views')

  4. 使用 res.render() 来渲染模板页面res.render('index.ejs', { 要渲染的数据对象 }),注意,模板页面的 后缀名,可以省略不写!

在 express 中配置 art-template

  1. 安装 两个包 cnpm i art-template express-art-template -S

  2. 自定义一个模板引擎  app.engine('自定义模板引擎的名称', 渲染函数)

  3. 将自定义的模板引擎,配置为 express 的默认模板引擎  app.set('view engine', '具体模板引擎的名称')

  4. 配置 模板页面得存放路径 app.set('views', '路径')

使用 express 框架中提供的路由来分发请求

  1. 什么是路由:路由就是对应关系;

  2. 什么叫做后端路由:前端请求的URL地址,都要对应一个后端的处理函数,那么 这种URL地址到 处理函数之间的对应关系,就叫做后端路由;

  3. 在Express中,路由的主要职责 就是 把请求分发到对应的处理函数中

  4. 在Express中,如何 定义并使用路由呢?

js

// 1. 封装单独的 router.js 路由模块文件const express = require('express')// 创建路由对象const router = express.Router()

router.get('/', (req, res)=>{})
router.get('/movie', (req, res)=>{})
router.get('/about', (req, res)=>{})// 导出路由对象module.exports = router
  1. express 创建的 app 服务器,如何使用 路由模块呢?

js

// 导入自己的路由模块const router = require('./router.js')// 使用 app.use() 来注册路由app.use(router)

注册路由方式

  • app.get()

    • 请求路径必须完全匹配

    • 方式必须是 get

  • app.post()

    • 请求路径必须完全匹配

    • 方式必须是 post

  • app.use()

    • 请求路径中第一部分只要与 '/index' 相等即可,并不要求完全匹配

    • 进行路由匹配的时候不限定方法

  • app.all()

    • 请求路径必须完全匹配

    • 进行路由匹配的时候不限定方法

通过 正则 注册路由

1,方式是 get

2,请求路径以/index开头即可

app.get(/^\/index(\/.+)*$/,(req, res)=>{
    res.send('hi!');
})

Express 框架里 中间件的概念

1. 什么是中间件

定义:中间件就是一个处理函数;只不过这个函数比较特殊,包含了三个参数,分别是 reqresnext

注意:中间件方法中的三个参数:

  • req:请求对象;

  • res:响应对象;

  • next:next()可以被调用,表示调用下一个中间件方法;

webp

中间件

2. Express 框架中对中间件的5种分类

  1. 应用级别的中间件: 挂载到 app 上的中间件 app.get('URL地址', (req, res, next)=> {})

  2. 路由级别的中间件: 挂载到 router 对象上的中间件  router.get('url地址', (req, res, next)=>{})

  3. 错误级别的中间件: 回调函数中,有四个参数 app.use((err, req, res, next)=>{})

  4. 唯一内置的中间件: express.static()

  5. 第三方中间件: 非express框架提供的,需要程序员手动安装才能使用的中间件;body-parser 解析post 表单数据

中间件的概念,了解即可,因为实际开发中,我们都直接使用第三方现成的中间件;

express中获取参数的几种形式

  1. 获取 http://127.0.0.1:3001/user?id=10&name=zs 中的查询参数:

  • 直接使用 req.query 获取参数即可;

  • 注意:URL 地址栏中通过 查询字符串 传递的参数,express 框架会直接解析,大家只需要使用 req.query 直接获取 URL 中 查询字符串的参数;

从URL地址中获取路径参数:

通过 req.params 获取路由中的参数

 app.get('/news/:yeas/:month/:day',(req, res)=>{
     res.send(req.params);
 })
  • 假设后台的路由是 app.get('/user/:id/:name', (req, res) => {})

  • 假设客户端浏览器请求的URL地址为:http://127.0.0.1:3001/user/10/zs

  • 直接使用 req.params 可以获取URL地址中传递过来的参数;

从post表单中获取提交的数据:

  • 借助于body-parser来解析表单数据

  • 安装:npm i body-parser -S

  • 导入:const bodyParser = require('body-parser')

  • 注册中间件:app.use(bodyParser.urlencoded({ extended: false }))

  • 使用解析的数据: req.body 来访问解析出来的数据

Web 开发模式

1. 混合模式(传统开发模式)

  • 以后端程序员为主,基本上不需要前端程序员,或者,前端程序员只负责画页面、美化样式、写JS特效,前端程序员不需要进行数据的交互;

  • 这种开发模式,在早些年比较常见;

  • 传统开发模式下,用的最多的是 Jquery + 模板引擎 + Bootstrap

  • 后端页面 .php   .jsp   .aspx   .cshtml

2. 前后端分离(趋势)

  • 后端负责操作数据库、给前端暴露接口

  • 前后端分离的好处:保证了各个岗位的职责单一;

  • 前端负责调用接口,渲染页面、前端就可以使用一些流行的前端框架 Vue, React, Angular

MVC

webp

MVC

JSONP 和 CORS 的区别

  1. JSONP的原理:动态创建script标签;

  • JSONP发送的不是Ajax请求

  • 不支持 Post 请求;

  1. CORS中文意思是跨域资源共享 ,需要服务器端进行 CORS 配置;

  • CORS 发送的是真正的Ajax请求

  • CORS 支持Ajax的跨域

  • 如果要启用 CORS 跨域资源共享,关键在于 服务器端,只要 服务器支持CORS跨域资源共享,则 浏览器肯定能够正常访问 这种 CORS 接口;而且,客户端在 发送 Ajax的时候,就像发送普通AJax一样,没有任何代码上的变化;

  1. 对于Node来说,如果想要开启 CORS 跨域通信,只需要安装cors的模块即可;

day 6

HTTP协议的无状态性

  1. HTTP协议的通信模型:基于请求 - 处理 - 响应的!

  2. 由于这个通信协议的关系,导致了HTTP每个请求之间都是没有关联的,每当一个请求完成之后,服务器就忘记之前谁曾经请求过!

  3. 如果纯粹基于HTTP通信模型,是无法完成登录状态保持的!每次请求服务器,服务器都会把这个请求当作新请求来处理!

  4. 我们可以通过 cookie 技术,实现状态保持,但是由于cookie是存储在客户端的一门技术,所以安全性几乎没有,因此不要使用cookie存储敏感的数据!

cookie介绍

1. 什么是cookie,作用是什么

  • 由于Http协议是无状态的,且传统服务器只能被动的响应请求,所以,当服务器获取到请求的时候,并不知道当前请求属于哪个客户端!

  • 服务器为了能够明确区分每个客户端,需要使用一些小技术,来根据不同的请求区分不同的客户端;

  • 只要有请求发生,那么必然对应一个客户端,我们可以在每次客户端发起请求的时候,向服务器自动发送一个标识符,告诉服务器当前是哪个客户端正在请求服务器的数据;

  • 如何提供这个标识符呢?我们可以在请求头(Request Headers)中添加一个标签,叫做cookie,这样,每次发送请求,都会把这个cookie随同其他报文一起发送给服务器,服务器可以根据报文中的cookie,区分不同的客户端浏览器。

  • 如何在客户端请求头中添加标识符?

  • 在Node中可以在writeHeader的时候,通过Set-Cookie来将cookie标识通过响应报文发送给客户端!

  • 客户端也可以通过一些方式来操作自己的cookie,比如通过jquery.cookie这个插件!

2. cookie的基本使用

var http = require('http');var server = http.createServer();

server.on('request', function (req, res) {    // 解析cookie
    var cookies = {};    var cookieStr = req.headers.cookie; // 从请求的headers中获取cookie信息
    cookieStr && cookieStr.split(';').forEach(function (item) {        var parts = item.split('=');
        cookies[parts[0].trim()] = parts[1].trim(); // 将cookie解析出来,保存到对象中
    });

    res.writeHeader(200, {        'Content-Type': 'text/plain; charset=utf-8',        "Set-Cookie": ['issend=ok', 'age=20']
    });    if(cookies.issend ==='ok'){
        res.end('不要太贪心哦!');
    }else{
        res.end('呐,赏你一朵小红花~~');
    }
});

server.listen(4000, function () {    console.log('服务器已启动!');
});

3. 通过expires设置Cookie的过期时间

// 设置 过期时间 为60秒之后// 注意:在设置过期时间的时候,需要将时间转换为 UTC 格式var expiresTime = new Date(Date.now() + 1000 * 60).toUTCString();
res.writeHeader(200, {  'Content-Type': 'text/html; charset=utf-8',  'Set-Cookie': ['isvisit=true;expires=' + expiresTime, 'test=OK']
});
res.end('<h3>你好,欢迎光临,送给你一个苹果!</h3>');

GMT和UTC有什么区别?格林尼治标准时(GMT)与世界时(UTC)是怎么回事

4. cookie可以被伪造,不安全

使用谷歌插件edit this cookie,就能伪造cookie数据!所以不要使用cookie存储敏感的数据!比如登录状态和登录信息;
一些敏感的数据,应该存储都服务器端!

5. 什么是Cookie的应用场景

  1. 对安全性要求不高

  2. 不需要存储大量的数据

  3. 主要应用场景,是用来做 客户端 与 服务器之间的 状态保持技术;

登录退出及状态保存

1 使用express-session来保存登录状态

1.1 什么是session

由于HTTP是无状态的,所以服务器在每次连接中持续保存客户端的私有数据,此时需要结合cookie技术,通过session会话机制,在服务器端保存每个HTTP请求的私有数据;

1.2 session原理

在服务器内存中开辟一块地址空间,专门存放每个客户端私有的数据,每个客户端根据cookie中保存的私有sessionId,可以获取到独属于自己的session数据。

webp

session原理

1.3 在express中使用session

  1. 安装session模块npm install express-session -S

  2. 导入session模块

     var session = require('express-session')
  3. 在express中使用session中间件:

     // 启用 session 中间件
     app.use(session({
       secret: 'keyboard cat', // 相当于是一个加密密钥,值可以是任意字符串
       resave: false, // 强制session保存到session store中
       saveUninitialized: false // 强制没有“初始化”的session保存到storage中
     }))
  4. 将私有数据保存到当前请求的session会话中:

     // 将登录的用户保存到session中
     req.session.user = result.dataValues; // 设置是否登录为true
     req.session.islogin = true;
  5. 通过destroy()方法清空session数据:

     req.session.destroy(function(err){   if(err) throw err;   console.log('用户退出成功!');   // 实现服务器端的跳转,这个对比于 客户端跳转
       res.redirect('/');
     });

day7

MD5 的特性

  1. MD5 是一种加密算法,在调用这个算法的时候,提供一个密码的明文, 调用的结果,得到一个 32 位长度的密文;

  2. MD5 算法的特性:相同的字符串,如果多次调用 md5 算法,得到的结果,完全一样;

  3. MD5 算法,无法被逆向解密

  4. 但是,基于 md5 算法的第二个特性,我们可以进行碰撞暴力破解;(MD5 存在被暴力破解的安全性问题)

  5. 为了解决 简单的明文密码,被 md5 加密后,通过 暴力破解的安全性问题, 然后就出现了加盐的MD5加密;

  6. 目前,md5的暴力破解,又升级了,升级到了 彩虹表

  7. 由于彩虹表出现,我们推荐大家,在存储网站密码的时候,使用 bcrypt 加密算法,得到加密之后的密文进行存储;

bcrypt 加密算法

  1. 在调用加密算法的时候,需要手动提供一个 幂次;

  2. 调用加密算法,得到的加密结果格式:$版本号$循环的幂次$22位的随机盐 31位的密文

  • 加密的随机盐加密的幂次,和加密算法的版本号已经被存储到了真正的密文中;

项目中使用 bcrypt 的步骤

  1. 运行 npm i node-pre-gyp -g

  2. 在项目根目录中,打开终端,运行 cnpm install bcrypt -S

  3. 导入 bcrypt

     // 导入加密的模块
     const bcrypt = require('bcrypt')
  4. 定义幂次:

     // 定义一个 幂次
     const saltRounds = 10    // 2^10
  5. 调用 bcrypt.hash() 加密:

     // 加密的方法
     bcrypt.hash('123', saltRounds, (err, pwdCryped) => {   console.log(pwdCryped)
     })
  6. 调用bcrypt.compare()对比密码是否正确:

     // 对比 密码的方法
     bcrypt.compare('123', '$2b$10$i1ufUKnC9fXTsF9oqqvLMeDnpNfYIvhyqKRG03adiebNFPkjW3HPW', function(err, res) {  console.log(res)  // 内部对比的过程:
      // 1. 先获取 输入的明文
      // 2. 获取输入的密文
      // 2.1 从密文中,解析出来  bcrypt 算法的 版本号
      // 2.2 从密文中,解析出来 幂次
      // 2.3 从密文中,解析出来前 22 位 这个随机盐
      // 3. compare 方法内部,调用 类似于 hash 方法 把 明文,幂次,随机盐 都传递进去     最终得到正向加密后的密文
      // 4. 根据最新得到的密文,和 compare 提供的密文进行对比,如果相等,则 返回 true ,否则返回 false;
     })


使用模板引擎处理公共部分

在PHP中,抽取公共的区域,直接使用PHP语法就行;
但是,在Express的框架中,并没有抽取页面公共部分的语法,需要模板引擎提供这样的语法;

添加文章并跳转到文章详情

  1. 发表文章之前,需要使用 第三方的插件,叫做 markdown + editor => mditor

  2. 注意:mditor这个第三方模块,提供了两个功能:

  • 功能1: 可以当作一个纯粹的MarkDown编辑器插件,在前端页面中使用;

  • 功能2: 在Node端,我们可以require('mditor'),使用这个模块,提供的方法,把markdown文本,解析转换为HTML内容;



作者:小浅_JJY
链接:https://www.jianshu.com/p/6a3a9c66ba36


点击查看更多内容
7人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消