nodejs入门

199 阅读11分钟

这是我参与8月更文挑战的第8天,活动详情查看: 8月更文挑战

NODE.JS

一、基本概述

1.概述

1)对比JavaScript和node.js

JS运行在客户端浏览器,存在多个解释器,存在代码兼容性;Nodejs运行在服务器端,只有一种解释器,不存在兼容性

两者都有相同的内置(ES)对象,自定义对象,不同的宿主对象

JS用于开发浏览器端的交互效果,Nodejs用于服务器端开发,数据库的操作,文件的操作,其它服务器的调用...

2)相关网站

nodejs.org 英文官网

nodejs.cn 中文镜像

3)运行方式

脚本模式

node 拖拽文件 回车

交互模式

node 回车 进入到交互模式

​ 两次ctrl+c 退出交互模式

4)node.js特点

支持数万个并发连接,常用于基于社交网络的大规模WEB应用

本身属于是单线程运行,不适合那些CPU密集型的操作

2.全局对象

1)global

在Nodejs下全局变量和全局函数都是可以使用global来访问到的。

2)console

log() 打印日志

info() 打印消息

warn() 打印警告

error() 打印错误

time() 开始计时

timeEnd() 结束计时

开始计时和结束计时提供的参数要保持一致

3)process
进程
arch查看当前的CPU架构
platfrom查看当前的操作系统
version查看当前node.js版本号
pid查看当前进程编号
kill()结束指定编号的进程
4)Buffer

缓冲区、缓冲器,在内存中临时存储数据的区域,常用于存储网络传输的资源

let buf=Buffer.alloc(5, 'abcde'); //创建buffer,分配5个字节空间,存储数据

一个英文字母占1个字节,一个汉字占3个字节

String(buf) / buf.toString() //转为字符串

二、基本模块

模块是一个功能体

一个模块引入其它的模块,一个模块其它的模块所引入

分为自定义模块、核心模块、第三方模块

Nodejs自动给每个模块添加了一个函数,文件中的代码自动被函数所包含,里边的变量和函数都是局部的,所形成的作用域称为模块作用域。 (function(){ 文件中的代码 })
module.exports 公开的内容,也就是导出的对象,引入该模块会得到这个对象
require() 是一个函数,用于引入其它的模块

1.模块相关

require: 是一个函数,用于引入其它模块

module: 当前模块的对象

module.exports: 当前模块的导出对象

__dirname: 当前模块的绝对目录 directory

__filename: 当前模块的绝对目录和模块名称

2.模块分类

以路径开头以路径开头
文件模块require('./circle.js') 常用于引入自定义模块require('url') 常用于引入官方提供的核心模块
目录模块require('./02_dong') 首先会到02_dong目录下寻找package.json文件中寻找main对应的文件,如果没有则会自动寻找index.jsrequire('ran') 会自动到当前目录下node_modules目录中寻找,如果找不到会一直往上一级目录下的node_modules中寻找。用于引入第三方模块

../上一级

a/ 下一级

论述:如果执行require('mysql'),是如何引入模块的。
会到当前目录下的node_modules中寻找mysql目录,如果找不到,会一直往上一级目录下的node_modules中寻找mysql目录;找到后,接着到mysql目录下去寻找package.json中main对应的文件,如果找不到会自动去寻找index.js

3.npm和包

包(package): 是第三方模块

npm:是用来管理包的工具,包含下载安装、更新、卸载、上传...

npm在安装nodejs的时候会附带的安装

npm -v 查看版本号

1)切换命令行目录

①cd 目录的路径 回车

盘符名称: 例如d: 如果涉及到盘符的变化需要运行这一步

②在要进入的目录下空白区域,按住shift,单击鼠标右键,选择'在此处打开powershell窗口'

2)npm下载安装

官网:www.npmjs.com

npm install 包的名称 回车

会将下载的包放入到node_modules中,如果node_modules目录不存在会自动创建。同时会生成文件package-lock.json,用于记录包的版本号。

4.查询字符串模块(querystring)

查询字符串:浏览器向服务器发请求,传递数据的一种方式,位于网址(URL)中

jd.com/search?kw=d…

查询字符串模块是用来操作查询字符串的工具

parse() 将查询字符串解析为对象,可以获取传递的数据了

5.URL模块

URL: 互联网上的资源都有对应的网址,这个网址就称为URL

www.codeboy.com:9999/products.ht…

协议 域名/IP地址 端口 文件的路径 查询字符串

URL模块用于操作URL

parse() 将URL解析为对象,获取各个部分 查询字符串部分(query)

6.定时器

1)一次性定时器
let timer=setTimeout(()=>{
  console.log('boom!');
},3000);
//清除
clearTimeout(timer);
/*
三秒打印,clearTimeout这条是清除所以会不显示打印内容。
3000是秒
*/
2)周期定时器
let timer=setInterval(() => {
    console.log('boom');
    //每打印1次加1
    i++;
    //当i为3的时候,清除定时器
    if (i === 3) {
        clearInterval(timer);
    }
}, 3000);
/*
如果写的是一次性定时器,则不能进行循环直接打印一次
*/
3)立即执行的定时器
console.log(2);
setImmediate(() => {
    console.log(1);
});
process.nextTick(() => {
    console.log(4);
});
console.log(3);
/*
2
3
4
1
*/

7.文件系统模块(fs)

在nodejs下文件包含文件形式和目录形式

使用前需要先引入模块

const fs=require('fs');//名字叫什么都行
1)查看文件的状态

isDirectory() 是否为目录

isFile() 是否为文件

fs.stat( 文件的路径, 回调函数 ) / fs.statSync( 文件的路径 )

回调函数 用于获取结果

err 可能产生的错误

s 获取到的状态对象

//同步、
console.log(fs.statSync("文件名"));
//异步
fs.stat("文件名",(err,s)=>{
    if(err){
		throw err;
    }
    console.log(s);
    /*
    console.log(s.inFile());
    console.log(s.isDirectory());
    */
})

2)创建目录

fs.mkdirSync( 目录的路径 )

fs.mkdirSync("./com1");
fs.mkdir("./com2", (err) => {
    if (err) {
        throw err;
    }
})
3)移除目录

fs.rmdirSync( 目录的路径 )

fs.rmdirSync("./com1");
fs.rmdir("./com2", (err) => {
    if (err) {
        throw err;
    }
})
4)读取目录

fs.readdir(文件的路径, 回调函数) / fs.readdirSync(文件的路径)

回调函数

err 可能产生的错误

result 读取到的目录结果,格式为数组

console.log(fs.readdirSync("文件路径"));
fs.readdir("文件路径",(err,s)=>{
	console.log(s);
})
/*
打印出文件夹中的东西
*/
5)写入文件
(1)覆盖写入

fs.writeFile(文件的路径, 数据, 回调函数) / fs.writeFileSync( 文件的路径,数据 )

如果文件不存在,则创建文件然后写入数据

如果文件已经存在,会覆盖原来的内容写入

fs.writeFileSync("文件名", "覆盖内容");
fs.writeFile("文件名", "覆盖内容", (err) => {});
(2)追加写入

fs.appendFile(文件的路径, 数据, 回调函数) / fs.appendFileSync(文件的路径, 数据)

如果文件不存在,则创建文件然后写入数据

如果文件已经存在,在末尾追加写入内容

fs.appendFile("文件名", "需要追加的内容", (err) => {});
fs.appendFileSync("文件名", "需要追加的内容");
6)读取文件

fs.readFile(文件的路径, 回调函数) / fs.readFileSync(文件的路径)

fs.readFile("1.txt", (err, s) => {
  console.log(s.toString());//转字符,否为为buffer乱码
});

console.log(fs.readFileSync("1.txt").toString());
7)删除文件

fs.unlink(文件的路径,回调函数) / fs.unlinkSync(文件的路径)

fs.unlinkSync("1.txt");
fs.unlink("1.txt", (err) => {});
8)检测文件是否存在

fs.existsSync(文件的路径)

//使用循环的方法进行查看是否存在
if (fs.existsSync("./ko")) {
  console.log("ok");
}
9)拷贝文件

fs.copyFile( 源文件的路径, 目标文件的路径, 回调函数 ) / fs.copyFileSync(源文件的路径, 目标文件的路径)

fs.copyFile("1.js", "2.js", (err) => {});
fs.copyFileSync("1.js", "3.js");
10)文件流

createReadStream(文件的路径) 创建可读取的文件流

createWriteStream(文件的路径) 创建可写入的文件流

8.同步和异步

同步:在运行的过程中,会阻止后续代码的执行,只有运行完才能往后执行,通过返回值来获取结果

异步:在运行的过程中,不会阻止后续代码的执行,在一个独立的线程执行,执行完以后将结果以回调函数的形式放入到事件对列,通过回调函数来获取结果。

三、web服务

1.http

http协议是浏览器和web服务器之间的通信协议

1)通用的头信息

Request URL: 请求的URL,向服务器端请求的资源

Request Method: 请求的方法 get/post

Status Code: 响应的状态码

1**: 正在响应,还没有结束

2**: 成功的响应

3**: 响应的重定向,跳转到另一个URL

4**: 浏览器端请求错误

5**: 服务器端错误

2)响应的头信息

Content-Type: 设置响应的内容的类型 html -> text/html

Location: 跳转的URL,通常会结合着状态码3**使用

3)请求的头信息
4)请求主体

表单传递的数据,如果没有数据此项为空

5)创建web服务器
//引入http模块
const http=require('http');
//创建web服务器
const app=http.createServer();
//设置端口
app.listen(8080);
//根据浏览器的请求作出响应
//通过事件作出响应
app.on('request',(req,res)=>{
  //req 请求的对象
  //req.url  获取请求的URL
  //req.method  获取请求的方法
  console.log(req.url, req.method);
  //res 响应的对象
  //参数1:设置响应状态码
  //参数2:可选的,设置响应的头信息
  //res.writeHead(302,{
  //  Location:'http://www.tmooc.cn'
  //});
  //设置响应的内容
  res.write('这是你的jianbing');
  //结束并发送响应
  res.end();
});

2.ExPress

1)创建web服务器
const express=require('express');
const app=express();//将express模块导出
app.listen(8080);//设置web服务器端口
2)路由

用来处理特定的请求,包含有请求的方法、请求的URL、回调函数。

只有请求的方法和请求的URL同时匹配,才会执行回调函数。

res 响应的对象

res.send() 设置响应的内容并发送

res.sendFile() 设置响应的文件并发送,文件需要使用绝对路径 __dirname

res.redirect() 设置响应的重定向,跳转另一个URL

req 请求的对象

req.method 获取请求的方法

req.url 获取请求的URL

req.query 获取查询字符串传递的数据,格式为对象

app.get('需要响应的网页地址',(res,req)=>{
    res.send();
    res.sendFile('完整的目录');
    res.sendFile(__dirname+'在同一目录下需要转的文件');
    res.redirect('http://www.baidu.com');
})
对比get和post两种请求方法
get请求传递的数据以查询字符串传递,可能被浏览器所缓存,速度相对块,传递的数据不超过4k
传递方式格式获取
get传递查询字符串req.query 格式为对象
post传递流(不可见)通过事件获取 req.on('data', (chunk)=>{ //chunk是分段的数据,格式为buffer,需要转字符串,转完后为查询字符串,需要解析为对象 })
路由传参通过URLreq.params 格式为对象

路由传参

导入express后使用

app.get('需要访问的地址',(req,res)=>{
    res.send('访问成功');//可以用来测试是否成功
})

3.路由器

项目开发中,可能出现不同模块下相同的URL,为了团队协作,独立出每个功能模块,使用路由器将当前模块下所有的路由放到一起,并给URL添加前缀,最后挂载到web服务器下

//创建路由器
const express=require('express');
const r=express.Router();
r.get('/list',(req,res)=>{
    res.send('');//写入显示的内容
})
module.exports=r;

//在web服务器下引入访问并挂在
const userRouter=require('文件路径');//导入文件
//挂载路由器到web服务器下,添加前缀
//参数1:添加的前缀 /user  访问形式  /user/list
//参数2:要挂载的路由器
app.use('/user',userRouter);

4.中间件

中间件为路由服务的,用于拦截对路由的请求,也可以作出响应。

中间件分为应用级中间件、路由级中间件、内置中间件、第三方中间件、错误处理中间件

1)应用级中间件
app.use(url,(req,res,next)=>{})

url 表示要拦截的URL,对应路由中的URL,一旦拦截会自动执行回调函数

next 是一个函数,表示往后执行下一个中间件或者路由

2)路由级中间件

路由器的使用

app.use( '/product', productRouter )
3)内置中间件

托管静态资源(html,css,js,图像...)

当浏览器端请求文件,不需要通过路由去寻找文件,而是让浏览器自动到指定的目录下去寻找。

app.use( express.static('目录路径') )
4)第三方中间件

属于第三方模块,需要提前下载安装

使用body-parser将post请求数据解析为对象

//1.引入body-parser模块
const bodyParser=require('body-parser');
//2.使用body-parser中间件,会将所有post请求数据解析为对象
app.use( bodyParser.urlencoded({
  //是否使用扩展的模块qs,true表示使用,false表示不使用,会自动使用querystring模块
  extended: false
}) );
//3.在路由中获取对象格式数据
req.body

4.MySQL模块

nodejs操作mysql数据库的工具模块

下载安装 npm install mysql

1)创建普通链接
const c=mysql.createConnection( {  } )  //需要提供mysql连接的相关内容 
c.connect()  // 测试连接,可以省略
c.query(sql命令, 回调函数)  //要执行的SQL命令,通过回调函数获取结果
/*
 回调函数
   err  可能产生的错误
   result   具体SQL命令的执行结果
*/
2)创建链接池
pool.query( SQL命令, 要过滤的数据, 回调函数 )
//要过滤的数据格式为数组,过滤完会自动替换到SQL命令中的占位符
pool.query('DELETE FROM emp WHERE eid=?',['5 or 1=1'],(err,result)=>{
  if(err) throw err;
  console.log(result);
});

具有攻击性:DELETE FROM emp WHERE eid=5 or 1=1;

1=1 所有的数据都满足这个条件

占位符(?): 会对用户提供的条件进行过滤,把具有攻击性的条件给删除。