目录
1、Node 基础语法
属于后端开发 是个js的代码运行环境 用Js语法进行开发后端
命令行工具powershell
打开你要进入的node文件的当前位置,按住shift再点击右键打开powershell,就是当前位置了
Cd : 切换到文件夹
. / : 当前文件夹
. . / :上一个文件夹;
Node.js模块开发
因为在js中,有两大问题文件依赖和命名冲突
模块的导入和导出
Node,js中规定一个js文件就是个一个模块,模块内部的变量和函数在默认情况下在外部都无法得到,解决办法:
方法1:模块内部可以使用exports对象进行成员导出,使用require方法导入其他模块
代码:
//a.js
//在模板内部定义变量
let version =1.0;
//在模块中定义方法
const sayHi=name=>`您好,${name}`;
//向模块外导出数据
exports.version=version;
exports.sayHis=sayHi;
//b.js
//在b模块中带入模块a
let a=require('./b.js');
//输出结果
console.log(a.version);
console.log(a.sayHis('terry'));
方法2:模块内部可以使用module.exports对象进行成员导出,使用require方法导入其他
如果exports和module.export指向不同的的对象,以module.exports为准
系统模块
node运行环境提供的API,因为这些API都是以模块化的方式进行开发的,所以我们又称为node运行环境提供的API为系统模块
Fs文件操作 fs.readFile
语法:
const fs =require('fs');//引入模块
fs.readFile('文件路径、文件名称','文件编码',callback);
案例:
const fs = require('fs');
fs.readFile('./01.helloworld.js','utf8',(err,doc)=>{
//err是一个对象,包含错误信息
//文件读取成功err是null
//doc是文件读取结果
console.log(err);
console.log(doc);
}
Fs文件操作 fs.writeFile
会覆盖原有内容
语法:
const fs =require('fs');//引入模块
Fs.writeFile ('文件路径/文件名称','数据',callback);
const fs = require('fs');
fs.writeFile('./demo.txt','hello,world',err=>{
if(err!=null){
console.log(err);
return;
}
console.log('文件写入成功');
})
Path路径操作
语法: path.join ( ‘路径’ ,‘路径’…….)
//导入系统模块
const path =require('path');
//路径拼接
let finialPath = path.join('itcast','a','b','c.css');
console.log(finialPath);
相对路径和绝对路径
const fs =require('fs');
const path = require('path');
console.log(__dirname)
console.log(path.join(__dirname,'01.js'));
fs.readFile(path.join(__dirname,'01.js'),'utf8',(err,doc)=>{
console.log(err);
console.log(doc);
});
第三方模块
npmjs.com
又名为 包
Npm : node的第三方模块管理工具
下载:npm install 模块名称
Eg: npm install formidable(已下载) // 会下载到当前命令行目录下面
卸载:npm unintall package 模块名称
Eg: npm unintall package formidable (已下载)
以上是本地安装
nodemon
是一个命令行工具,辅助项目开发
在node.js中每次修改文件都需要在命令行工具中重新执行一遍文件,非常麻烦,而nodemon可以自动更新命令行界面
使用步骤:
- npm install nodemon -g
- 在命令行工具中用nodemon代替node
nrm
下载地址切换工具,npm地址在国外所以下载慢
使用步骤:
- npm install nrm -g
- nrm ls //查询地址列表
- nrm use 下载地址 //下载地址名称
2、gulp工具
基于node平台开发的前端构架工具
gulp作用
- 项目上线,HTML,css,js文件压缩合并、
- 语法转换(es6、less.....)
- 公共文件抽离
- 修改文件浏览器自动刷新
gulp用法
npm install gulp
在项目根目录下建立gulpfile.js文件
重构项目文件夹结构
1、 src目录放置源代码文件
2、 dist目录放置构建后的文件
在gulpfile.js文件里编写代码
在命令行工具中执行gulp任务
gulp插件
都是需要安装的,且用法不同,要查文档
node-modules文件夹的问题
- 安装gulp插件后会在当前文件里生成node-modules文件夹
- 但是文件夹过多过碎,在拷贝文件时传输速度会很慢
- 复杂的模块依赖关系需要被记录,确保模块版本和当前保持一致,否则会导致当前项目运行报错
为了解决不拷贝node-modules文件,项目就跑不起来的问题
Package.json文件
- 项目描述文件,记录了当前项目名称、版本、作者、github地址、依赖了那些第三方模块等
- 使用 npm install -y 生成
-
收到没有node-modules文件夹,只需要在根目录下的命令行界面输入npm install,就会根据json文件自动补全再在第三方模块
项目依赖
- 在项目开发阶段和线上运营阶段,都需要依赖的第三方包,称之为项目依赖
- 使用 npm install包命令下载 的文件会被默认添加到Package.json文件的dependencies字段里
-
{ "dependencies":{ "jquery":"^3.3.1" } }
开发依赖
- 在项目开发阶段需要依赖,线上运营不需要依赖的第三方包,称之为开发者依赖
- 使用npm install 包名 --save-dev命令将包添加到Package.json文件的devdependencies字段里
-
{ "devDependencies":{ "gulp":"^3.9.1" } }
Package-lock.json文件
- 锁定包的版本,确保下载时不会因为包版本不同而产生问题
- 加快下载速度,因为文件里已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装只需要下载即可
模块加载机制
3、服务器端基础概念
URL
统一资源定位符,又叫URL,是专为标识internet网上资源位置而设置的一种编制方式,我们平时所说的网页地址指的即是URL.
开发过程中客户端和服务器端
4、创建web服务器
编写完后记得在命令行里,用node app.js打开服务器,在浏览器中打开本地网页输入网址:local host:端口号
HTTP协议概念
超文本传输协议,规定了如何从网站服务器传输超文本到本地浏览器,它基于客户服务器架构工作,是客户端(用户)和服务器(网站)请求和应答的标准
报文
在HTTP请求和响应过程中传递的数据块叫报文,包括要传递的数据和一些附加信息,并且遵守一定的格式
请求报文
两种请求方式:
- GET 请求数据
- POST 发送数据
请求地址:
//创建服务器
const http = require('http');
const app = http.createServer();
app.on('request',(req,res)=>{
if(req.method=='post'){
res.end('post')
}else if(req.method=='GET'){
res.end('get')
}
})
app.listen(3000);
console.log('服务器启动成功');
<!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>Document</title>
</head>
<body>
<form method="post" action="http://localhost:3000">
<input type="submit" name="" id="">
</form>
</body>
</html>
- method:请求方式
- action:请求地址
-
. method获取:请求方式
获取请求地址
- req.url
- console.log(req.url)
if(req.url=='./index.html'){
res.end('hompage');
}else if(req.url=='./list'){
res.end(listpage);
}else{
res.end('not found');
}
获取报文信息
- req.headers
console.log(req.headers);
响应报文
- HTTP状态码 就是一种标识符,可以自己随意修改
- 200请求成功
- 404请求资源没找到
- 500服务器端错误
- 400客户端请求有语法错误32
修改办法:
- res.writeHead()
app.on(request',(req,res)=>{
res.weriteHead(400);
})
内容类型:不同的文件不同的解析
- Text/html
- Text/css
- Text/plain : 纯文本
- Application/javascript
- Image/jpeg
- Application/json
fs.readFile(realPath,(error,result)=>{
if(error!=null){
res.writeHead(404,{
'content-type':'text/html,charset=utf8'
})
res.end('文档读取失败');
return;
}
HTTP的请求和响应的处理
客户端向服务端发送请求时,有时需要携带一些客户消息,客户消息需要通过请求参数的形式传递到服务器端,比如登录操作
GET请求参数
参数会被放置在浏览器地址栏中,例如:http://localhost:3000/?name=zhangsan&age=20
只是一个标识,有时看上去是路径,其实和本地的真实路径可能会不同
服务器端处理请求参数的办法: . parse()
Const url = require(‘url’); //内置模块
url.parse(req.url); //内置模块里的方法,会处理请求参数
console.log( url . parse(req.url) );
console.log( url . parse(req.url, ture) ); //会把请求参数处理成一个对象返回
. parse(req,res,ture) 添加第二个参数会把结果处理成一个对象
let{query,pathname}=url.parse(req.url,ture);
console.log(query.name);
console.log(query.age);
if(pathname=='./index'||pathname=='/'){
res.end('<h2>欢迎来到index</h2>');
}else if(pathname=='./list'){
res.end('welcome to listpage');
}else{
res.end('not found')
}
POST请求参数
请求参数的位置:
- post参数是通过事件的方式来接受的
- 当请求参数传递的时候出发data事件
- 当参数传递完成的时候出发end事件
- 使用querystring系统模块将参数转换为对象格式
const http=require('http');
const app =http.createServer();
app.on('request',(req,res)=>{
let postParams='';
req.on('data',params=>{
postParams+=params;
});
req.on('end',()=>{
console.log(querystring.parse(postparams));
}); //通过内置模块优化成对象形式
});
res.end('ok');
路由
路由是指客户端请求地址和服务器端程序代码的对应关系,简单的说,就是请求什么响应什么
静态资源
服务器不需要处理,可以直接响应给客户端的资源就是静态资源,例如:css、javascrpt、image
静态资源访问功能实现:
const http =require('http');
const url =require('url');
const path =require('path');
const fs =require('fs');
const mime =require('mime');//可以自动判断访问文件的文件类型并返回值
// 引入系统模块---------------------------
const app=http.createServer();
app.on('request',(req, res)=> {
// 获取用户请求路径-----------------------
let pathname=url.parse(req.url).pathname;
pathname =pathname =='/'?'/default.html':pathname //三元表达式
// 将会用户请求路径转换为服务器的硬盘路径-----------------------
let realPath=path.join(__dirname,'public' + pathname)
let type= mime.getType(realPath); //返回资源类型
// console.log(mime.getType(realPath));
fs.readFile(realPath,(error,result)=>{
if(error!=null){
res.writeHead(404,{
'content-type':'text/html,charset=utf8'
})
res.end('文档读取失败');
return;
}
res.writeHead(200,{
'content-type':type
})
res.end(result)
});
});
app.listen(3000);
console.log('服务器启动成功');
动态资源
相同的请求地址不同的响应资源,这种资源就是动态资源
Node.js异步编程
同步API,异步API
同步api:只有当前api执行完成后,才能执行下一个api
异步API:当前api执行不影响后续代码的执行,异步无法通过返回值的方式拿到api的结果,要通过回调函数
function getMsg(){
setTimeout(function(){
return{msg:'hello node,js'}
},2000);
}
const msg =getMsg(); //undefined
回调函数
自己定义函数让别人去调用
function getMsg(callback){
setTimeout(function(){
callback({
msg:'hello node.js'
})
},2000)
}
getMsg(function(data){
console.log(data); //hello node.js
});
异步API
fs.readFile('./demo.txt',(err,result)=>{});
var server = http.createServer();
server.on('request',(req,res)=>{});
如果异步api后面的代码的执行依赖当前异步api的执行结果,后面的代码在执行时异步api还没有返回结果
例如:依次读取a文件,b文件,c文件
const fs =require('fs');
fs.readFile('./1.txt','utf8',(err,result1)=>{
console.log(result1)
fs.readFile('./2.txt','utf8',(err,result2)=>{
console.log(result2)
fs.readFile('./3.txt','utf8',(err,result3)=>{
console.log(result3)
})
})
});
嵌套回调太多,难以维护称为回调地狱
Promise
promise的出现就是为了解决node.js异步编程中回调地狱的问题
let promise =new promise ((resolve,reject)=>{
setTimeout(() => {
if(ture){
resolve({name:'张三'})
}else{
reject('失败了')
}
}, 2000);
});
promise.then(result=>console.log(result));
.catch(error=>console.log(error));
支持链式编码,成功就调用resolve,失败就用reject
let promise =new promise ((resolve,reject)=>{
fs.readFile('./100.txt','utf8',(err,result)=>{
if(err!=null){
reject(err);
}else{
resolve(result);
}
});
});
promise.then(result=>console.log(result));
.catch(error=>console.log(err));
异步函数
async function fn({
throw '错误';
return 123;
})
fn().then(function(data){
console.log(data);
}).catch(function(err){
console.log(err);
})
Await关键字:
- 它只能出现在异步函数中
- Await promise它可以暂停异步函数的执行 等待promise对象返回
- 只能写在promise后面
async function p1(){
return 'p1'
}
async function p2(){
return 'p2'
}
async function p3(){
return 'p3'
}
async function run(){
let r1 =await p1()
let r2 =await p2()
let r3 =await p3()
console.log(r1);
console.log(r2);
console.log(r3);
}
使用异步函数优化后的需求
const fs=require('fs');
const promisify =require('util').promisify;//改造现有异步函数函数API,让其返回promise对象,从而支持异步函数语法
const readFile =promisify(fs.readFile);//原版readfile不能返回promise
async function run(){
let r1 =await readFile('./1.text','utf8')
let r2 =await readFile('./2.text','utf8')
let r3 =await readFile('./3.text','utf8')
}
run();
const promisify =require('util').promisify;//改造现有异步函数函数API,让其返回promise对象,从而支持异步函数语法
const readFile =promisify(fs.readFile);//原版readfile不能返回promise
node.js全局对象global
在浏览器中全局对象是window,在node中全局对象是global