Node.js随笔

语言 和 环境(平台) 之间的关系:
1. 语言(HTML和css不属于语言),是编写代码的语法规范;程序员遵循特定的语法规范,编写出来的代码,只是单纯的文本字符串而已,并不具备可执行的特点;
2. 环境(平台),提供了执行代码的能力,如果程序员编写的代码想要成功执行,必须要依赖于特定的执行环境;
- 例如:Javascript代码可以被浏览器中的JS解析引擎执行;
- 所以,浏览器,就是一个 Javascript 的执行环境;因为 Javascript 代码可以在浏览器中被执行;

  1. 前端主要工作:
    1. 页面结构;
    2. 美化页面样式;
    3. 书写页面的业务逻辑;
    4. 使用Ajax调用后台接口;
  2. 后端主要工作:
    1. 操作数据库;
    2. 对外暴露操作数据库的API接口;
  3. 前后端协作开发;

Node.js: 基于Chrome V8引擎的JavaScrip服务器端运行环境;
1. Node.js 中 Javascript 的组成部分
- ECMAScript 核心 + 全局成员 + 核心 API 模块
- 全局成员:console、setInterval、setTimeout。。。
- 核心 API 模块:就是 Node 平台 单独提供的一些API,这些API是Node平台所独有的;
2. 注意:Node.js 中 没有 BOM 和 DOM;

js中的异步:定时器、ajax;异步在同步之后才执行!;

var 关键字;有如下主要缺点:
- 存在变量提升问题,降低 js 代码的可阅读性
- 没有块级作用域,容易造成变量污染;

let 主要特性:
- 不存在变量提升问题,只有定义之后才能使用此变量;
- 不能重复声明;
- 有 { } 作用域(块级);
- let定义的变量不会挂载到window上面;

const 主要特性:
- 不存在变量提升问题,只有定义之后才能使用此变量;
- const 定义的常量,无法被重新赋值;指向不能改变;
- 当定义常量的时候,必须定义且初始化,否则报语法错误;
- const 定义的常量,也有 块级作用域;
- const定义对象里面的值可以修改;

一旦let和const声明过的变量,var就不能再次声明;

闭包:函数嵌套函数;
函数内部可以使用外部的变量;
缺点:内存泄漏;解决:手动赋值变量为空null;

解构赋值:把某个对象中的属性,当作变量,给解放出来,这样,今后就能够当作变量直接使用了;
let{原属性名:新属性名} = user;
使用场景:数组、交换变量;

箭头函数:(形参列表) => { 函数体代码 };
1. 本质上就是一个匿名函数;
2. 箭头函数的特性: 箭头函数内部的 this, 永远和 箭头函数外部的 this 保持一致;
3. 不能当做构造函数;也不能通过arguments提取实参;

变体:
	- 变体1:如果箭头函数,左侧的形参列表中,只有一个参数,则,左侧小括号可以省略;
		var add = x =>{
			return x+10;
		};

	- 变体2:如果右侧函数体中,只有一行代码,则,右侧的 { } 可以省略,return也要省略;
		var add = (x,y) => x+y;

	- 变体3:如果箭头函数左侧 只有一个 形参,而且右侧只有一行代码,则 两边的 () 和 {} 都可以省略;return也要省略;
		var add = x => x+10;

this指向:1.正常函数调用者;2.方法;3.new 出来的实例对象;4.箭头函数指向外部;

对象快捷定义属性和方法:

ES6 通过class创建对象 class Fn {};var fn1 = new Fn();

API:
fs :
导入fs核心模块;:const fs = require(‘fs’);
1:读取文件:fs.readFile(‘路径’,‘编码格式默认为null’,function(err,data){
console.log(err): err如果为null证明读取读取成功;
consloe.log(data); data为读取到的数据;
err.message:报错信息;
});

2:写入文件:fs.writeFile(‘写入路径', '写入的数据', '文件格式默认为utf-8',function(err) {
		console.log(err): err如果为null证明写入成功;	
		});
	注意:文件不存在时,则直接写入,如果文件已存在,则会覆盖!

3:追加文件:fs.appendFile('路径', '追加的内容', '文件格式默认为utf-8', function(err){
		console.log(err): err如果为null证明追加成功;		
		});
	注意:如果追加的文件不存在,会先创建,后追加!

4.读取指定路径信息:fs.stat('指定路径' , function(err,stats) {
			stats.size:大小,单位是字节Byte;
			stats.birthtime: 创建时间;
			stats.isFile():判断是否是文件;
			stats.isDirectory();判断是否是目录(文件夹);
		} );

5.复制文件:fs,copyFile('被拷贝的的路径', '要拷贝到哪里', function(err,){
		if(err) return console.log(err.message);拷贝失败;
		
		});

路径问题:
在node中: __dirname 表示当前这个文件所处的目录;
(__dirname + ‘/文件夹名/文件名’);
node里的相对路径:相对于node所执行的目录来说的,不是相对于文件名;
绝对路径:
__dirname 永远以文件所在的目录来说的;只是代表一层目录;
__filename: 表示当前这个文件的完整路径,包含文件名;

路径操作:
引入模块:const path = require(‘path’);
1:拼接路径片段:path.join( ); …/会把前面的字符抵消;
2:获取文件的名称:path.basename();
3:获取文件夹所在的路径:path.dirname();
4:获取文件的扩展名:path.extname();

Javascript 的单线程和异步:
Javascript 的解析和执行一直是单线程的,但是宿主环境(浏览器或node)是多线程的;

异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务, 交给主线程执行;

Javascript解析引擎,一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行。

Node中的API为什么几乎都是异步操作:
1. 什么样的操作需要使用异步处理:要把 耗时的操作,放到异步中去执行;

2. 异步执行任务的好处:能够提高 耗时的任务它的执行效率,提高 JS 解析引擎的工作效率;

模块化:代码的一种规范;node.js遵循的是common.js规范;高内聚,低耦合;

全局作用域:全局作用域使用 global 来访问,类似于浏览器中的window;
每个 Javascript 文件,都是一个单独模块,每个模块都有自己独立的作用域,因此:模块中的成员,默认无法被其它模块访问。
默认在node中,每个js文件中定义的方法变量,都属于模块作用域的;

模块作用域:
1. module(模块标识)
module 属性是 Common JS 规范中定义的,它是一个对象,表示当前这个具体的 js 模块;
2. require(引用模块)
每一个实现了 CommonJS 规范的模块,必须定义一个 require() 函数,使用这个 require 函数,就能够 很方便的导入其它 模块中的成员,供自己使用;
3. exports(暴露模块成员)
每一个模块中,如果想要把自己的一些私有成员,暴露给别人使用,那么,必须实现一个 exports 对象,通过exports对象,可以方便的把模块内私有的成员,暴露给外界使用;

module.exports 和 exports 的关系:
1. module.exports 和 exports 默认引用了同一个空对象;
2. module.exports 和 exports 作用一致,都可以向外暴露成员;
3. 一个模块作用域中,向外暴露私有成员时,永远以 module.exports 为准;
4.在以后开发中推荐使用module.exports;

AMD/CMD:
浏览器端不能使用 CommonJS规范;因为 CommonJS 下,模块是同步加载的;AMD/CMD可以理解为是commonjs在浏览器端的解决方案,AMD/CMD下,模块都是异步加载的;
1. AMD模块化规范代表:RequireJS (node)
- 主要特性1:对于依赖的模块,AMD 是提前执行;
- 主要特性2:推崇依赖前置;
2. CMD模块化规范代表:SeaJS (seaJavaScript)
- 主要特性1:对于依赖的模块,CMD 是延迟执行;CMD 推崇 as lazy as possible.
- 主要特性2:推崇依赖就近;

模块成员的分类: 核心模块、第三方模块(不需要写路径)、用户自定义模块(需要写路径);

包Packages:
包可以看作是 模块、代码 和 其它资源 组合起来形成的 独立作用域;

规范:
	1:包都要以一个单独的目录而存在;
	2. package.json 必须在包的顶层目录下;
	3. package.json 文件必须符合 JSON 格式,并且必须包含如下三个属性:name, version, main;
		- name:  包的名字
		- version: 包的版本号
		- main: 表示包的入口文件;(以对象的形式暴露)
	4. 二进制文件应该在bin目录下;

	5. javaScript代码应该在lib目录下; ./lib/main.js 
	6. 文档应该在doc目录下;
	7. 单元测试应该在test目录下;
	8.README.md 说明文档;

NPM(Node package manager):
1. NPM 是一个 第三方模块的托管网站,指的就是https://www.npmjs.com/;
2. NPM 是Node的包管理工具(全名叫做 Node package manager),在我们安装Node时候,就已经顺便也安装了 NPM 这个管理工具;
3:npm i 包名 -g :装全局;
4:npm init -y : 初始化一个package.json的配置文件;
5:npm uninstall 包名:卸载;
6:npm i -S : 表示线上也需要;
7:npm i -D: 表示开发的时候需要,上线后不需要;

创建最基本的web服务器:
- const http = require(‘http’);

- 创建服务器:使用 const server = http.createServer() 创建服务器;

- 绑定监听事件:通过 server.on('request', function(req, res) { 请求的处理函数 }) 绑定事件 并 指定 处理函数;reg:请求对象;res:响应对象;

- 防止响应内容中文乱码问题: res.writeHeader(200, { 
			'Content-Type': 'text/plain; charset=utf-8'
			});

-使用 req.url 获取客户端请求的URL地址;

-以html标签的格式解析: res.writeHeader(200, { 
			'Content-Type': 'text/html; charset=utf-8'
			});
-res.end()里面只能接受字符串和二进制sever

- 启动服务器:通过 server.listen(端口, IP地址, 启动成功的回调函数) 来启动服务器;

template(路径,要渲染的数据)

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

express:
创建基本的 express 服务器:
- 导入 express 第三方模块;
- 创建服务器的实例:调用 const app = express() 方法;
- 通过 app.get() 或 app.post() 方法,来监听客户端的 get 或 post 请求,具体语法:
- 监听 GET 请求:app.get(‘请求地址’, (req, res) => { 处理函数 })
- 监听 POST 请求: app.post(‘请求地址’, (req, res) => { 处理函数 })
- 启动 express 服务器:通过 app.listen(端口, IP地址, 启动成功后的回调函数) 启动服务器;

快捷方法
	1. res.send():
		1. 支持 发送 字符串 Content-Type: text/html;
		2. 支持 发送 对象 或 数组 Content-Type: application/json
		3. 支持 发送 二进制Buffer 此时会当作文件下载;
	2. res.sendFile():
		- 一个参数:必须是绝对路径;
		            res.sendFile(path.join(__dirname, './view/index.html'));

		- 两个参数:第一个可以传相对路径,第二个为绝对路径;
	                            res.sendFile('./view/movie.html', { root: __dirname });

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

快速托管静态资源:
app.use()方法,是专门用来注册 中间件:
express.static(‘托管的目录’) 是express的内置中间件;可以把指定的目录托管为静态目录,那么指定所有的文件都可以直接用浏览器访问;
app.use(express.static(’./test’));
可以在托管静态资源文件的时候,指定要挂载的虚拟路径:
app.use(’/虚拟目录’, express.static(’/test’))

ejs 模板引擎:
1. 安装 ejs 模板引擎npm i ejs -S
2. 使用 app.set() 配置默认的模板引擎 app.set(‘view engine’, ‘ejs’)
3. 使用 app.set() 配置默认模板页面的存放路径 app.set(‘views’, ‘./根目录’)
4. 使用 res.render() 来渲染模板页面res.render(‘要渲染的页面’, { 要渲染的数据对象 }), 注意,模板页面的 后缀名,可以省略不写;

在 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’, ‘路径’);

路由:
1. 什么是路由:路由就是对应关系;
2. 什么叫做后端路由:前端请求的URL地址,都要对应一个后端的处理函数,那么 这种URL地址到 处理函数之间的对应关系,就叫做后端路由;
3. 在Express中,路由的主要职责 就是 把请求分发到对应的处理函数中;
4. 在Express中,如何 定义并使用路由呢?

 		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
	
 		2.使用 路由模块
	const express = require('express');
	const app = express();
	//导入自己的路由模块
 		 const router = require('./router.js')
  		// 使用 app.use() 来注册路由
  		app.use(router);

中间件:
作用:共享数据,一定是有顺序的;
定义:中间件就是一个处理函数;只不过这个函数比较特殊,包含了三个参数,分别是 req,res,next;
注意:中间件方法中的三个参数:
- req:请求对象;(共享数据)
- res:响应对象;(共享数据)
- next:next()可以被调用,表示调用下一个中间件方法;

Mysql的使用:
const express = require(‘express’)
const app = express()
//导入mysql模块
const mysql = require(‘mysql’)
//创建mysql链接对象
const conn = mysql.createConnection({
host:“127.0.0.1”,
database:‘mysql_001’,
user:‘root’,
password:‘root’
})
/* 查询 /
//直接调用.query()查询:第一个参数:要执行的mysql语句,第二个参数:处理结果的回调函数;
/
const sqlstr = ‘select * from user’
conn.query(sqlstr, (err, res) =>{
if(err) return console.log(‘获取数据失败’+err.message);
console.log(res);

}) */

/* 新增 /
/
const users = {id:2,name:‘erhei’,age:12,gender:‘女’}
//set ? :代表新增的数据
const sqlstr2 = ‘insert into user set ?’
conn.query(sqlstr2, users, (err, res) =>{
if(err) return console.log(‘新增数据失败’+err.message);
console.log(res);
}) */

/* 修改 /
/
const users = {id:2,name:‘erhei’,age:18,gender:‘女’}
//set ?:代表要修改的数据 where id=?:修改数据的id
const sqlstr3 = ‘update user set ? where id=?’
conn.query(sqlstr3,[users,users.id], (err,res) =>{
if(err) return console.log(‘修改数据失败’+err.message);
console.log(res);
}) */

/* 删除 */
const sqlstr4 = ‘delete from user where id=?’
conn.query(sqlstr4,2,(err,res) =>{
if(err) return console.log(‘删除数据失败’+err.message);
console.log(res);
})
app.listen(3000, () =>{
console.log(‘http://127.0.0.1:3000’);

})

模块加载机制:
优先从缓存中加载:
- 当一个模块初次被 require 的时候,会执行模块中的代码,当第二次加载相同模块的时候,会优先从缓存中查找,看有没有这样的一个模块!
- 好处:提高模块的加载速度;不需要每次都重新执行并加载模块;

核心模块的加载机制:
- 先查找缓存;如果缓存中没有,再去加载核心模块;

用户模块的加载机制(不会一层一层向上查找):
- 先查找缓存;
- 如果缓存中没有则尝试加载用户模块;
- 如果在加载用户模块时候省略了后缀名,查找规则:
index -> index.js -> index.json -> index.node;

第三方模块查找机制:一层一层向上查找;

获取参数:
1:req.query();:获取地址栏的参数返回对象;

2:req.params();:获取restful风格的url,需要在参数前加冒号:动态匹配;
	路由:app.get('/user/ :id/ :name', (req, res) => {});
	前台URL地址为:http://127.0.0.1:3001/user/10/zs;
3: 从post表单中获取提交的数据:
	- 借助于body-parser来解析表单数据
	- 安装:npm i body-parser -S
	- 导入:const bodyParser = require('body-parser')
	- 注册中间件:app.use(bodyParser.urlencoded({ extended: false }))
	- 使用解析的数据: req.body 来访问解析出来的数据;

JSONP 和 CORS 的区别:
1. JSONP的原理:动态创建script标签;
- JSONP发送的不是Ajax请求
- 不支持 Post 请求;

2. CORS跨域资源共享 ,需要服务器端进行 CORS 配置;
	- CORS 发送的是真正的Ajax请求
	- CORS 支持Ajax的跨域
	- 如果要启用 CORS 跨域资源共享,关键在于 服务器端,只要 服务器支持CORS跨域资源共享,则 浏览器肯定能够正常访问 这种 CORS 接口;而且,客户端在 发送 Ajax的时候,就像发送普通AJax一样,没有任何代码上的变化;
注意:后端不存在跨域问题,它是解决跨域的;

安装格式化时间包:npm i moment -S;
body.ctime = moment().format(‘YYY-MM-DD HH:mm:ss’);

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

session原理:(把用户的状态保存在服务端)
在服务器内存中开辟一块地址空间,专门存放每个客户端私有的数据,每个客户端根据cookie中保存的私有sessionId,可以获取到独属于自己的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. 注销:req.session.destroy(function( ){
		// 实现服务器端的跳转,这个对比于 客户端跳转
		res.redirect('/');
	});

token:存在于服务端,存的是一套加密的算法;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值