✍ 目录脑图
🔥Nodejs冲浪笔记 | 地址 |
---|---|
🔥Nodejs基础之JavaScript模块化(一) | https://blog.csdn.net/Augenstern_QXL/article/details/119941988 |
🔥nodejs基础之包管理工具npm(二) | https://blog.csdn.net/Augenstern_QXL/article/details/119990575 |
🔥Nodejs基础之常用模块(三) | https://blog.csdn.net/Augenstern_QXL/article/details/119942024 |
🔥Nodejs基础之Express框架和art-template引擎(四) | https://blog.csdn.net/Augenstern_QXL/article/details/119942262 |
✍Node是什么
-
Node 是一个基于 Chrome V8 引擎的 JavaScript 代码运行环境。
-
浏览器(软件)能够运行JavaScript代码,浏览器就是JavaScript代码的运行环境
-
Node(软件)能够运行JavaScript代码,Node就是JavaScript代码的运行环境
-
Node文档中文网:http://nodejs.cn/api/url.html#url_new_url_input_base
1、第一个Node程序
- 新建 app.js
- 输入代码块
node-http-server
,自动生成 Node 结构(安装插件:Node-snippets就可以快捷生成)
- 在终端使用
node app.js
运行程序
- 假如要停止我们的服务器,在终端处按
ctrl + c
停止服务器
1.1、解析第一个Node程序
- 引入 http 模块
var http = require("http");
-
创建服务器
接下来我们使用
http.createServer()
方法创建服务器,并使用listen
方法绑定 3000 端口。函数通过 request、response 参数来接收和响应数据
//表示引入http模块
var http = require('http');
/*
request 获取客户端(浏览器)传过来的信息
response 给浏览器响应信息
*/
http.createServer(function (request, response) {
//发送响应头
//设置HTTP头部,状态码是200,文件类型是 html,字符集是 utf8
response.writeHead(200, {'Content-Type': 'text/html;charset=UTF-8'});
//表示给我们页面上面输出一句话并且结束响应
response.end('Hello World');
}).listen(3000); //监听端口
2、内置模块HTTP
Node.js中,将很多的功能,划分为一个个 module(模块)。 Node.js 中的很多功能都是通过模块实现。
//表示引入http模块
var http = require('http');
/*
request 获取客户端(浏览器)传过来的信息
response 给浏览器响应信息
*/
http.createServer(function (request, response) {
//发送响应头
//设置HTTP头部,状态码是200,文件类型是 html,字符集是 utf8
response.writeHead(200, {'Content-Type': 'text/html;charset=UTF-8'});
//表示给我们页面上面输出一句话并且结束响应
response.end('Hello World');
}).listen(3000); //监听端口
那我们如果想在屏幕上输出汉字呢?
var http = require('http');
http.createServer(function(request, response) {
//发送响应头
response.writeHead(200, { 'Content-Type': 'text/html;charset=UTF-8' });
//表示给我们页面上面输出一句话并且结束响应
response.write('你好 Nodejs');
response.end('<h2>你好 Nodejs</h2>');
}).listen(3000); //监听端口
如何解决 Preview 里面的乱码状态呢?只需要在http.createServer
中添加下方代码即可
res.write("<head> <meta charset='UTF-8'></head>"); //解决乱码
2.1、创建服务器
创建服务器对象,我们是通过 createServer 来完成的
- req:request请求对象,包含请求相关的信息
- res:response响应对象,包含我们要发送给客户端的信息
2.2、监听主机和端口号
通过listen方法来开启服务器,并且在某一个主机和端口上监听网络请求
listen函数有三个参数:
- 端口port: 可以不传, 系统会默认分配端
- 主机host: 通常可以传入localhost、ip地址127.0.0.1,或者ip地址0.0.0.0,默认是0.0.0.0
- 回调函数:服务器启动成功时的回调函数
// 启动服务器,并且制定端口号和主机
server.listen(8888, '0.0.0.0', () => {
console.log("服务器启动成功~");
});
2.3、request对象
在向服务器发送请求时,我们会携带很多信息,比如:
- 本次请求的URL,服务器需要根据不同的URL进行不同的处理
- 本次请求的请求方式,比如GET、POST请求传入的参数和处理的方式是不同的
- 本次请求的 headers 中也会携带一些信息,比如客户端信息、接受数据的格式、支持的编码格式等
这些信息,Node会帮助我们封装到一个request的对象中,我们可以直接来处理这个request对象
const http = require('http');
// 创建一个web服务器
const server = http.createServer((req, res) => {
// request对象中封装了客户端给我们服务器传递过来的所有信息
console.log(req.url);
console.log(req.method);
console.log(req.headers);
res.end("Hello Server");
});
// 启动服务器,并且制定端口号和主机
server.listen(8888, '0.0.0.0', () => {
console.log("服务器启动成功~");
});
2.4、URL的处理
客户端在发送请求时,会请求不同的数据,那么会传入不同的请求地址:
- 比如http://localhost:8000/login
- 比如http://localhost:8000/products
服务器端需要根据不同的请求地址,作出不同的响应
// 创建一个web服务器
const server = http.createServer((req, res) => {
//最基本的使用方式
if (req.url === '/login') {
res.end("欢迎回来~");
} else if (req.url === '/users') {
res.end("用户列表~");
} else {
res.end("错误请求, 检查~");
}
那么如果用户发送的地址中还携带一些额外的参数呢?
比如:http://localhost:8000/login?name=why&password=123
这个时候,url的值是 /login?name=why&password=123
我们如何对它进行解析呢?使用内置模块url
3、url模块
3.1、旧版url API
我们来看一下 req 里面能够使用的东西。
- 最重要的是
req.url
属性,表示用户的请求URL 地址。所有路由设计,都是通过req.url
来实现的。
const http = require('http');
http.createServer(function(request, response) {
console.log(request.url);
//发送响应头
response.writeHead(200, { 'Content-Type': 'text/html;charset="UTF-8"' });
//表示给我们页面上面输出一句话并且结束响应
response.write('你好 Nodejs');
response.end('<h2>你好 Nodejs</h2>');
}).listen(3000); //监听端口
这里注意一下输出是在 Nodejs 控制台输出,而不是在浏览器上输出。因为输出是在服务端,浏览器是客户端
- 我们比较关心的不是拿到 URL,而是识别这个 URL。
- 识别 URL,下面的 url 模块
旧版本 Node 的 url 用法如下:
url模块的使用 | 说明 |
---|---|
url.parse() | 解析 url(第二个参数为true,可以将 query 里面的数据转换为对象) |
url.format(urlObject) | 是上面 url.parse() 操作的逆向操作 |
url.resolve(from,to) | 添加或者替换地址 |
const url = require('url');
var api = 'http://www.itying.com?name=zhangsan&age=20';
//console.log(url.parse(api, true));
var getValue = url.parse(api, true).query;
console.log(getValue);
// ES6中模板字符串写法
console.log(`姓名:${getValue.name}--年龄:${getValue.age}`);
3.2、新版url API
新版本 Node 的 url 用法如下:
new URL(input,[,base])
:input
类型:String,要解析的绝对或相对的输入网址。如果 input 是相对的,则需要 base。如果 input 是绝对的,则忽略 base。
const myURL = new URL('/foo', 'https://example.org/');
// https://example.org/foo
const url = require('url');
const myURL = new URL(
"http://localhost:3000/p/a/t/h?name=zhangsan&age=20#hash");
console.log(myURL);
3.3、searchParams
searchParams 可以获取到 url 参数的 value
const myURL = new URL('https://example.org/?abc=123');
console.log(myURL.searchParams.get('abc'));
// 打印 123
myURL.searchParams.append('abc', 'xyz');
console.log(myURL.href);
// 打印 https://example.org/?abc=123&abc=xyz
myURL.searchParams.delete('abc');
myURL.searchParams.set('a', 'b');
console.log(myURL.href);
// 打印 https://example.org/?a=b
4、Nodejs工具
4.1、supervisor 工具
supervisor 会不停的watch 你应用下面的所有文件,发现有文件被修改,就重新载入程序文件这样就实现了部署,修改了程序文件后马上就能看到变更后的结果。麻麻再也不用担心我的重启nodejs 了
- 首先安装 supervisor(在cmd控制台输入下方代码)
npm install -g supervisor
- 使用 supervisor 代替 node 命令启动应用
supervisor app.js
4.2、nodemon
- nodemon 和 supervisor 的功能一样,两者安装一个即可
- 使用
npm install -g nodemon
下载它(-g 是全局安装) - 在命令行工具中用
nodemon
命令替代node
命令执行文件
nodemon app.js
5、内置模块fs
fs:file system ,文件操作系统,是系统模块,直接引入即可使用.
文件系统的API非常的多,我们不可能,也没必要一个个去学习,更多的是使用是时候去查对应的API
5.1、fs.stat🔥
fs.stat :检测是文件还是目录:
- 第一个参数是 path :路径
- 第二个参数是 callback:回调函数
const fs = require('fs');
// 1. fs.stat 检测是文件还是目录
fs.stat('./html',(err,data)=>{
if(err){
console.log(err);
return;
}
console.log(`是文件:${data.isFile()}`);
console.log(`是目录:${data.isDirectory()}`);
})
5.2、fs.mkdir🔥
fs.mkdir(): 创建目录
- 第一个参数 path:将要创建的目录路径
- 第二个参数 mode:目录权限(读写权限),默认为777
- 第三个参数 callback:回调函数,传递异常参数 err
fs.mkdir('./css',(err)=>{
if(err){
console.log(err);
return;
}
console.log('创建成功');
})
5.3、fs.writeFile🔥
fs.writeFile :创建写入文件
- 第一个参数 filename:文件名称
- 第二个参数 data:将要写入的内容,可以使用字符串或 buffer 数据
- 第三个参数 options:option 数组对象,包含
- encoding :可选值,默认为 ‘utf8’,当 data 使用 buffer 时,该值应该为 ignored
- mode:文件读写权限,默认为 438
- flag :默认为 ‘w’
- 第四个参数 callback:回调函数,传递一个异常参数 err
fs.writeFile('./html/index.html','你好nodejs',(err)=>{
if(err){
console.log(err);
return;
}
console.log('创建写入文件成功');
})
fs.writeFile('./html/index.html','你好nodejs 哈哈',(err)=>{
if(err){
console.log(err);
return;
}
console.log('创建写入文件成功');
})
注意:如果没有这个文件,则会新建一个文件,如果已经有这个文件,那么会覆盖这个文件里面的内容
5.4、fs.appendFile
fs.appendFile 追加文件
- 第一个参数 path:将要追加的文件路径
- 第二个参数 data:要追加的文件内容
- 第三个参数callback:回调函数,传递一个异常参数 err
fs.appendFile('./css/base.css','body{color:red}',(err)=>{
if(err){
console.log(err);
return;
}
console.log('appendFile 成功');
})
fs.appendFile('./css/base.css','h3{color:red}\n',(err)=>{
if(err){
console.log(err);
return;
}
console.log('appendFile 成功');
})
注意:如果这个文件不存在,则会新建文件,如果文件已经存在,则会在文件内容后面追加内容
5.5、fs.readFile
fs.readFile 读取文件:
- 第一个参数路径 path:想要读取的文件的路径
- 第二个参数callback:回调函数,传递一个异常参数 err 和读取的文件数据 data,data类型是 Buffer
fs.readFile('./html/index.html',(err,data)=>{
if(err){
console.log(err);
return;
}
console.log(data);
console.log(data.toString()); //把Buffer 转化成string类型
})
fs.readFile('./aaa/index.html',(err,data)=>{
if(err){
console.log(err);
return;
}
console.log(data);
console.log(data.toString()); //把Buffer 转化成string类型
})
5.6、fs.readdir
fs.readdir 读取目录:
fs.readdir('./html',(err,data)=>{
if(err){
console.log(err);
return;
}
console.log(data);
})
5.7、fs.rename
fs.rename :重命名,功能:1、表示重命名 2、移动文件
fs.rename('./css/aaa.css','./css/index.css',(err)=>{
if(err){
console.log(err);
return;
}
console.log('重命名成功');
})
fs.rename('./css/index.css','./html/index.css',(err)=>{
if(err){
console.log(err);
return;
}
console.log('移动文件成功');
})
5.8、fs.rmdir
fs.rmdir 删除目录
fs.rmdir('./aaaa',(err)=>{
if(err){
console.log(err);
return;
}
console.log('删除目录成功');
})
注意:要删除目录之前需要先删除目录下的所有文件
5.9、fs.unlink
fs.unlink 删除文件
fs.unlink('./aaaa/index.html',(err)=>{
if(err){
console.log(err);
return;
}
console.log('删除文件成功');
})
5.10、fs.createReadStream
fs.createReadStream: 从文件流中读取数据
const fs = require('fs');
// 以流的方式读取 data 目录下的 aaa.txt
var ReadStream = fs.createReadStream("./data/aaa.txt");
let count = 0;
var str = '';
// 通过 on 方法监听 data,表示我们读取到了这个数据
ReadStream.on('data', (data) => {
str += data;
count++;
})
// 通过 on 方法监听 end,表示我们读取完了这个数据
ReadStream.on('end', () => {
console.log(str);
console.log(count);
})
// 通过 on 方法监听 error,表示读取过程中的错误信息
ReadStream.on('error', (err) => {
console.log(err);
})
5.11、fs.createWriteStream
fs.createWriteStream:写入文件
const fs = require('fs');
for(var i=0;i<500;i++){
str +='我是从数据库获取的数据,我要保存起来'
}
// 以流的方式写到 data目录下的 output.txt
var writeStream = fs.createWriteStream('/data/output.txt');
writeStream.write(str);
//标记写入完成
writeStream.end();
writeStream.on('finish',()=>{
console.log('写入完成');
})
5.12、管道流🔥
管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。
const fs = require('fs');
// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');
// 创建一个可写流
var readStream = fs.createReadStream('output.txt')
// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readStream.pipi(writeStream);
console.log('程序执行完毕。');
6、同步与异步
6.1、同步API、异步API
- 同步API可以从返回值中拿到API执行的结果, 但是异步API是不可以的
// 同步
function sum (n1, n2) {
return n1 + n2;
}
const result = sum (10, 20); // 30
// 异步
function getMsg () {
setTimeout(function () {
return { msg: 'Hello Node.js' }
}, 2000);
// return undefined;
}
const msg = getMsg (); // undefined
- 同步API从上到下依次执行,前面代码会阻塞后面代码的执行
for (var i = 0; i < 100000; i++) {
console.log(i);
}
console.log('for循环后面的代码');
- 异步API不会等待API执行完成后再向下执行代码
console.log('代码开始执行');
setTimeout(() => { console.log('2秒后执行的代码')}, 2000);
setTimeout(() => { console.log('"0秒"后执行的代码')}, 0);
console.log('代码结束执行');
//代码开始执行
//代码结束执行
//"0秒"后执行的代码
//2秒后执行的代码
同步API 放在同步代码执行区,异步API放在异步代码执行区,同时将异步API 所对应的回调函数放在回调函数队列,这个时候注意,同步代码执行区和回调函数队列两者里面的代码没有执行,当同步代码区里面的内容执行完毕,这个时候去异步代码区,发现第二个 setTimeout 执行完毕,则将其对应的回调函数放入同步代码区执行,再去异步代码区发现第一个 setTimeout 执行完毕,再将其对应的回调函数放入同步代码区执行。
6.2、回调函数
自己定义函数让别人去调用。
回调函数视频讲解:https://www.bilibili.com/video/BV1UE411H71P?p=36
// getData函数定义
function getData (callback) {}
// getData函数调用
getData ( () => {});
getData 函数有一个形参 callback,传递的实参是一个函数,将一个函数作为另外一个函数的形参,则此形参就叫做回调函数。
function getData(callback) {
callback('123'); // 使用callback可以调用下面的匿名函数function,并给callback传递参数
//callback函数被调用了
}
// 调用函数
getData(function(n) {
console.log('callback函数被调用了');
console.log(n);
// 123
})
- 我们可以调用 callback 回调函数将异步API执行的结果传递出来
function getMsg (callback) {
// 调用callback将异步API执行的结果传递出来
setTimeout(function () {
callback ({ msg: 'Hello Node.js' })
}, 2000);
}
getMsg (function (msg) {
console.log(msg);
// { msg: 'Hello Node.js' }
});
6.3、Nodejs里面的异步API
fs.readFile('./demo.txt',(err,result) => {});
- 读取文件是需要时间的,文件读取的结果不能通过返回值的方式获取,需要通过回调函数。
var server = http.createServer();
server.on('request',(req,res) => {});
- 事件监测也是异步API
如果异步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);
})
})
})
回调嵌套的情况就叫做 回调地狱
6.4、Promise
Promise 出现的目的是解决 Node.js 异步编程中回调地狱的问题。
实际上,Promise 本身是一个构造函数,我们要解决回调地狱的问题,需要先使用 new 运算符创建 Promise 实例,在创建 Promise 实例的过程中,需要传入一个匿名函数,在匿名函数中有两个参数。
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({name: '张三'})
}else {
reject('失败了')
}
}, 2000);
});
promise.then(result => console.log(result) // {name: '张三'})
.catch(error => console.log(error); // 失败了)
例如,我们需要依次读取A文件、B文件、C文件
function p1() {
return new Promise((resolve,reject) => {
fs.readFile('./1.txt','utf8',(err,result) => {
resolve(result);
})
});
}
function p2() {
return new Promise((resolve,reject) => {
fs.readFile('./2.txt','utf8',(err,result) => {
resolve(result);
})
});
}
function p3() {
lreturn new Promise((resolve,reject) => {
fs.readFile('./3.txt','utf8',(err,result) => {
resolve(result);
})
});
}
p1().then((r1) => {
console.log(r1);
return p2(); //返回一个promise对象
})
.then((r2) => {
console.log(r2);
return p3();
})
.then((r3) => {
console.log(r3);
return p3;
})
6.5、ES7异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。
const fn = async () => {};
async function fn () {}
6.5.1、async关键字
- 普通函数定义前加async关键字 普通函数变成异步函数
- 异步函数默认返回promise对象
- 在异步函数内部使用return关键字进行结果返回 结果会被包裹在promise对象中 return关键字代替了resolve方法
- 在异步函数内部使用throw关键字抛出程序异常
- 调用异步函数再链式调用then方法获取异步函数执行结果
- 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
// 1. 普通函数定义前加async关键字,普通函数变成异步函数
// 2. 异步函数默认的返回值是promise 对象
async function fn() {
throw '发生了一些错误';
return 123;
}
fn ().then(function(data) {
console.log(data); //123
}).catch(function (err) {
console.log(err); //发生了一些错误
})
6.5.2、await关键字
- await关键字只能出现在异步函数中
- await promise await后面只能写promise对象 写其他类型的API是不可以的
- await关键字是暂停异步函数向下执行 直到promise返回结果
async function p1() {
return 'p1'; // 返回的是 promise 对象
}
async function p2() {
return 'p2';
}
async function p3() {
return 'p3';
}
async function run() {
await p1();
await p2();
await p3();
}
run();
简单理解:
- async 是让方法变成异步
- await 是等待异步方法执行完成
6.6、Node.js全局对象global
在浏览器中全局对象是 window,在 Node 中全局对象是 global。
Node 中全局对象有以下方法,可以在任何地方使用,global 可以省略
- console.log() 在控制台输出、
- setTimeout() 设置超时定时器
- clearTimeout() 清除超时定时器
- setInterval() 设置间歇定时器
- clearInterval() 清除间歇定时器
注意:Node中不存在 BOM、DOM,所以全局对象是 global。但是在 DOM、BOM 中也有这些方法,只是全局对象是 window。
6.7、获取异步方法里面的数据
6.7.1、回调函数获取
// 回调函数 获取异步方法里面的数据
function getData(callbck){
setTimeout(function(){
var name='张三';
callbck(name);
},1000);
}
//外部获取异步方法里面的数据
getData(function(data){
console.log(data+'111');
})
6.7.2、Promise获取
//Promise来处理异步 resolve 成功的回调函数 reject失败的回调函数
var p=new Promise(function(resolve,reject){
setTimeout(function(){
var name='张三';
if(Math.random()<0.7){
resolve(name);
}else{
reject('失败');
}
},1000);
})
p.then((data)=>{
console.log(data);
})
6.8、Async、Await使用
//普通方法
function test(){
return '您好nodejs';
}
console.log(test()); // 您好nodejs
//异步方法
async function test(){
return '您好nodejs';
}
console.log(test()); // Promise { '您好nodejs' }
async 是让方法变成异步,它返回的是 Promise,那我们要获取 Promise 对象里面的字符串要如何做呢?
//错误用法
async function test(){ // Promise { '您好nodejs' }
return '您好nodejs';
}
console.log(await test()); //错误 : await必须得用在async的方法里面
// 异步方法
async function test(){
return '您好nodejs';
}
// 正确获取异步方法里面的数据
async function main(){
var data=await test(); //获取异步方法里面的数据
console.log(data);
}
main();
我们当然最好是要返回的是 Promise 对象,否则也没必要将方法变为异步了。
// async 封装一个异步函数
async function test(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
var name='张三 222';
resolve(name);
},1000);
})
}
async function main(){
var data=await test(); //获取异步方法里面的数据
console.log(data);
}
main();
7、内置模块Path
7.1、path常见的API
- 从路径中获取信息
- dirname:获取文件的父文件夹
- basename:获取文件名
- extname:获取文件扩展名
const path = require('path');
// 1.获取路径的信息
const filepath = '/User/why/abc.txt';
console.log(path.dirname(filepath)); // /User/why
console.log(path.basename(filepath)); // abc.txt
console.log(path.extname(filepath)); // .txt
- 路径的拼接
- 如果我们希望将多个路径进行拼接,但是不同的操作系统可能使用的是不同的分隔符
- 这个时候我们可以使用
path.join
函数
// 2.join路径拼接
const basepath = '../User/why';
const filename = './abc.txt';
const othername = './why.js';
const filepath1 = path.join(basepath, filename);
console.log(filepath1); // ..\User\why\abc.txt
- 将文件和某个文件夹拼接
- 如果我们希望将某个文件和文件夹拼接,可以使用
path.resolve
- resolve 函数会判断我们拼接的路径前面是否有 / 或 …/ 或 ./
- 如果有表示是一个绝对路径,会返回对应的拼接路径
- 如果没有,那么会和当前执行文件所在的文件夹进行路径的拼接
- 如果我们希望将某个文件和文件夹拼接,可以使用
const path = require('path');
const basepath = '../User/why';
const filename = './abc.txt';
const othername = './why.js';
// 3.resolve路径拼接
// resolve会判断拼接的路径字符串中,是否有以/或./或../开头的路径
const filepath2 = path.resolve(basepath, filename, othername);
console.log(filepath2);
// E:\Code\Node\NodeCodeWhy\User\why\abc.txt\why.js
const path = require('path');
const basepath2 = '/User/coderwhy';
// const filename2 = '/why/abc.txt'; // E:\why\abc.txt
// const filename2 = './why/abc.txt'; // E:\User\coderwhy\why\abc.txt
// const filename2 = 'why/abc.txt'; // E:\User\coderwhy\why\abc.txt
// const filename2 = '../why/abc.txt'; // E:\User\why\abc.txt
const result = path.resolve(basepath2, filename2);
console.log(result);
7.1.1、path.extname
path.extname()
获取文件(可以是一个路径文件)的扩展名
const path = require('path');
console.log(path.extname('hello.md')); // md
// 获取路径信息的扩展名
let strPath = "http://www.xinhuanet.html";
console.log(path.extname(strPath)); // html
7.1.2、path.resolve
path.resolve([...paths])
把一个路径或路径片段的序列解析为一个绝对路径
const path = require('path');
let arr = ['/sxt', 'qianduan', 'zhongji'];
let info1 = path.resolve(...arr);
console.log(info1);
// D:\sxt\qianduan\zhongji
给定的路径的序列是"从右往左"被处理的,后面每个 path
被依次解析,直到构造完成一个绝对路径。
7.1.3、path.join🔥
path.join([...paths])
方法使用平台特定的分隔符把全部给定的path
片段连接到一起,并规范化生成的路径。
path.join(__dirname,'./02art-template.js')
path.join('/foo','bar','./baz');
// 'foo/bar/baz'
path.join('/foo','bar','/baz','..');
// 'foo/bar'
__dirname
获得当前执行文件所在目录的完整目录名__filename
获得当前执行文件的带有完整绝对路径的文件名
8、服务器端与客户端
网站应用程序主要分为两大部分:客户端和服务器端
- 客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTML、CSS、JS构建
- 服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。(可以将服务器端理解为另一台电脑)
9、路由
路由指的就是针对不同请求的URL,处理不同的业务逻辑。
const http = require('http');
const url = require('url');
http.createServer(function(request, response) {
response.writeHead(200, { 'Content-Type': 'text/html;charset=UTF-8' });
// 解构写法,相当于 request.url
const { url } = request;
if (url == '/' || url == 'index') {
response.end('欢迎来到首页');
} else if (url == '/list') {
response.end('欢迎来到列表页');
} else {
response.end('抱歉,您访问的页面出游了~');
}
response.end('Hello World');
}).listen(3000);
console.log('Server running at http://127.0.0.1:3000/');
9.1、Get请求
在客户端和服务器之间进行请求 - 响应时,两种最常被用到的方法是:GET 和 POST
- GET - 从指定的资源请求数据。(一般用于获取数据)
request.url
获取请求地址request.method
获取请求方法
- POST - 向指定的资源提交要被处理的数据。(一般用于提交数据)
http.createServer(function(request, response) {
//发送响应头
//设置HTTP头部,状态码是200,文件类型是 html,字符集是 utf8
response.writeHead(200, { 'Content-Type': 'text/html;charset=UTF-8' });
console.log(request.url); // 获取请求地址 /index.html
console.log(request.method); // 获取请求方法 GET/POST
//表示给我们页面上面输出一句话并且结束响应
response.end('Hello World');
}).listen(3000); //监听端口
9.1.1、GET请求参数
-
参数被放置在浏览器地址栏中,例如:http://localhost:3000/?name=zhangsan&age=20
-
参数获取需要借助系统模块url,url模块用来处理url地址
-
request.url
获取 /name=zhangsan&age=20 -
request.headers.host
获取 127.0.0.1:3000 -
const myURL = new URL(url, `http://{host}`);
-
如上获取到 url 对象,再从对象中获取参数
-
const http = require('http');
const url = require('url');
http.createServer(function(request, response) {
response.writeHead(200, { 'Content-Type': 'text/html;charset=UTF-8' });
// 解构写法,相当于 request.url
const { url } = request;
// 解构写法,相当于 request.headers.host
const { host } = request.headers;
if (url !== '/favicion.ico') {
const myURL = new URL(url, `http://{host}`);
response.write(`name: ${myURL.searchParams.get("name")},age: ${myURL.searchParams.get("age")}`);
}
response.end('Hello World');
}).listen(3000);
console.log('Server running at http://127.0.0.1:3000/');
9.2、Post请求
- 参数被放置在请求体中进行传输
- 获取 POST 参数需要使用 data 事件和 end 事件
- 使用 querystring 系统模块将参数转化为对象格式
const http = require('http');
// 处理请求参数模块
const queryString = require('querystring');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
// data 当请求参数传递的时候触发data事件
// end 当请求参数传递完成的时候触发end事件
let postParams = '';
request.on('data',(params)=>{
postParams += params;
})
request.on('end',()=>{
console.log(postParams); // 接收到的是一个字符串
console.log(queryString.parse(postParams)); // 使用queryString将字符串转化为对象
})
response.end('Hello World');
}).listen(3000);