0817 NOTE
从输入url到显示页面的整个过程是什么?
1.DNS解析,建立TCP连接,发送http请求
2.server接收到http请求,处理,并返回
3.客户端接收到返回的数据,处理数据
1.node的模块化开发
commonjs
//单个
module.exports = function(){
}
//多个
exports.a=function(){
}
exports.b=function(){
}
//导入
var main=require("./a");
var {a,b}=require("./b");
ES6
//注意:首先需要初始化,package.json文件中设置"type":"module",其次文件扩展名为mjs
//新建默认类
export default class Box{
constructor(){
}
}
//新建多个类
export function play(){
}
export var obj={
a:1,
b:2,
c:function(){
}
}
//导入
import Box from "./a.mjs";
import { play,obj } from "./b.mjs";
var b=new Box();
play();
console.log(obj);
TS
//首先初始化生成package.json文件 npm init -y
//其次初始化生成ts配置文件tsconfig.json tsc --init
//tsc中打开相应配置,确认导入文件夹和导出文件夹
/*
"target": "es5",
"module": "commonjs",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
*/
//添加ts项目依赖 npm i @types/node -S
//导出单个
export default class Box{
public constructor(){
}
public play():void
{
console.log("aaa")
}
}
//导出多个
export enum Color{RED="red",BLUE="blue",GREEN="green"};
export interface IUpdate{
update():void;
}
//导入
import Box from "./Box";
import {Color,IUpdate} from "./Utils";
var b:Box=new Box();
b.play();
console.log(Color.GREEN);
//执行 tsc -w后再执行
2.url与querystring
url:
const url = require("url");
//引入的url是一个对象
const url=require("url");
var httpURL="https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fcart.jd.com%2Fgate.action%3Fpid%3D10025238035933%26pcount%3D1%26ptype%3D1&r=1629163750325#/ab"
console.log(url.parse(httpURL));
/*
打印解析:
Url {
protocol: 'https:',
//协议:https
slashes: true,
auth: null,
host: 'passport.jd.com',
//域
port: null,
//端口号
hostname: 'passport.jd.com',
//主机名
hash: '#/ab',
//hash
search: '?ReturnUrl=http%3A%2F%2Fcart.jd.com%2Fgate.action%3Fpid%3D10025238035933%26pcount%3D1%26ptype%3D1&r=1629163750325',
//搜索部分
query: 'ReturnUrl=http%3A%2F%2Fcart.jd.com%2Fgate.action%3Fpid%3D10025238035933%26pcount%3D1%26ptype%3D1&r=1629163750325',
//去掉问号后的搜索部分
pathname: '/new/login.aspx',
//路径
path: '/new/login.aspx?ReturnUrl=http%3A%2F%2Fcart.jd.com%2Fgate.action%3Fpid%3D10025238035933%26pcount%3D1%26ptype%3D1&r=1629163750325',
//路径内容
href: 'https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fcart.jd.com%2Fgate.action%3Fpid%3D10025238035933%26pcount%3D1%26ptype%3D1&r=1629163750325#/ab'
}
//整个地址
//hash不能加在search前
*/
//format用法
var obj={
protocol:"https://",
hostname:"localhost",
port:4001,
hash:"abc",
search:"?a=1&b=2",
pathname:"/goodslist"
}
console.log(url.format(obj));
//https://:localhost:4001/goodslist?a=1&b=2#abc
//resolve 解决,替换节点关系
var str="http://www.163.com/goodslist/a/b";
console.log(url.resolve(str,"/shoppinglist"));//替换到根路径
console.log(url.resolve(str,"./shoppinglist"));//替换最后一个路径
console.log(url.resolve(str,"../shoppinglist"));//替换到上一个路径节点
console.log(url.resolve(str,"shoppinglist"));//替换到最后一个路径节点
var b = url.resolve('http://example.com/', '/one');
console.log(b)
/*
http://www.163.com/shoppinglist
http://www.163.com/goodslist/a/shoppinglist
http://www.163.com/goodslist/shoppinglist
http://www.163.com/goodslist/a/shoppinglist
http://example.com/one
*/
//URLSearchParams
//类似map,用来搜索地址中的参数,并且获取到指定的参数值
var u=new URL("/goodlist?a=1&b=2#abc","http://localhost:4001");
u.searchParams.append("c","3");
console.log(u.toString());
//http://localhost:4001/goodlist?a=1&b=2&c=3#abc
querystring:
querystring.decode()
querystring.decode()
函数是 querystring.parse()
的别名。
querystring.encode()
querystring.encode()
函数是 querystring.stringify()
的别名。
querystring.escape(str)
querystring.escape()
方法以针对网址查询字符串的特定要求优化的方式对给定的 str
执行网址百分比编码。
querystring.escape()
方法被 querystring.stringify()
使用,通常不会被直接使用。 导出它主要是为了允许应用程序代码在必要时通过将 querystring.escape
分配给替代函数来提供替换的百分比编码实现。
// console.log(querystring.escape("http://www.163.com/news/新闻摘要.html"))
// console.log(querystring.unescape("http%3A%2F%2Fwww.163.com%2Fnews%2F%E6%96%B0%E9%97%BB%E6%91%98%E8%A6%81.html"))
// console.log(encodeURIComponent("http://www.163.com/news/新闻摘要.html"));
// console.log(decodeURIComponent("http%3A%2F%2Fwww.163.com%2Fnews%2F%E6%96%B0%E9%97%BB%E6%91%98%E8%A6%81.html"));
/*
http%3A%2F%2Fwww.163.com%2Fnews%2F%E6%96%B0%E9%97%BB%E6%91%98%E8%A6%81.html
http://www.163.com/news/新闻摘要.html
http%3A%2F%2Fwww.163.com%2Fnews%2F%E6%96%B0%E9%97%BB%E6%91%98%E8%A6%81.html
http://www.163.com/news/新闻摘要.html
*/
3.path
引入:
const path = require("path")
使用:
//连接
//path.join()
console.log(path.join("http:\//localhost","list"))//error //path是本地路径
//http:\localhost\list
console.log(__dirname) //路径名称
//D:\webnote\third\GP25-third\node\0817\0817\path
console.log(path.join(__dirname,"abc"));
console.log(path.join(__dirname,"./abc"));
console.log(path.join(__dirname,"../abc"));//替换上一级的
console.log(path.resolve(__dirname,"abc"));
console.log(path.resolve(__dirname,"./abc"));
console.log(path.resolve(__dirname,"../abc"));
/*
D:\webnote\third\GP25-third\node\0817\0817\path\abc
D:\webnote\third\GP25-third\node\0817\0817\path\abc
D:\webnote\third\GP25-third\node\0817\0817\abc
D:\webnote\third\GP25-third\node\0817\0817\path\abc
D:\webnote\third\GP25-third\node\0817\0817\path\abc
D:\webnote\third\GP25-third\node\0817\0817\abc
*/
//resolve智能网成一个内容的替换,join可以完成多个连接符
console.log(__filename); //当前文件名和路径地址
//D:\webnote\third\GP25-third\node\0817\0817\path\a.js
var str=path.join(__dirname,"a.txt");
console.log(path.basename(str)) //文件名
console.log(path.extname(str)); //扩展名
/*
a.txt
.txt
*/
console.log(str.split(path.sep))//切割路径 sep返回路径关系
/*
[
'D:', 'webnote',
'third', 'GP25-third',
'node', '0817',
'0817', 'path',
'a.txt'
]
*/
4.http
//http.get()
//http.request()
//node可以是服务器,也可以作为客户端使用
//客户端向服务端发起请求,没有跨域的概念,只有浏览器向服务端发起请求时,才会出现跨域
//原因:客户端安装在计算器中,计算机对于客户端是允许认可状态,可以对计算机内容进行读写,对于计算机硬件有一定的操作权限
//客户端发起请求时,服务端返回消息给客户端,认为客户端对于返回的消息的读写没有问题,因此不存在跨域问题
//浏览器向服务端发起请求时,由于浏览器对于服务器没有读写的权限,具有非常高的不安全性,基于安全协议的考虑,对于非同域的状况,认为是不安全的,因此,需要认定为可安全读写的情况下才允许读入,这就是跨域问题的解决
//综上,可以获取一种新的解决跨域问题的方法:代理
5.events
var EventEmitter=require("events");
var {once}=require("events");
// 这种事件中事件和事件目标对象合为一体,事件本身完成抛发和侦听,可以在抛发中传参
var evt=new EventEmitter();
evt.on("abc",o=>{
console.log(o);
})
evt.emit("abc",{a:1});
//{a:1}
// const myEmitter = new EventEmitter();
// myEmitter.on('event', (a, b) => {
// setTimeout(() => {
// console.log('this happens asynchronously1',a,b);
// });//定点执行
// setImmediate(() => {
// console.log('this happens asynchronously',a,b);
// });//闲时执行
// });
// myEmitter.emit('event', 'a', 'b');
//都是异步宏任务,但是谁先执行无法判断
//o n 事件的创建与监听 emit 事件的抛发 off 事件的删除
Node.js EventTarget 对比 DOM EventTarge
Node.js EventTarget
和 EventTarget Web API之间有两个主要区别:
- 尽管 DOM
EventTarget
实例可能是分层的,但 Node.js 中没有层次和事件传播的概念。 也就是说,调度到EventTarget
的事件不会通过嵌套目标对象的层次结构传播,这些目标对象可能每个都有自己的事件句柄集。 - 在 Node.js
EventTarget
中,如果事件监听器是异步的函数或者返回Promise
,并且返回的Promise
拒绝,则该拒绝会被自动捕获并按照同步抛出的监听器的方式处理。
6.file
引入:
var fs = require("file")
//var fsp = require("fs/promise")
// 创建文件夹
// fs.mkdir("abc",function(err){
// console.log(err);
// });
// 删除文件夹
// fs.rmdir("abc",function(err){
// console.log(err);
// })
// 判断文件是否存在
// fs.exists("a.js",function(bool){
// console.log(bool);
// })
// 判断是否路径存在,判断这个信息是否是文件或者文件夹
// fs.stat("a.js",function(err,stats){
// // console.log(stats);
// console.log(stats.isDirectory());
// console.log(stats.isFile());
// })
案例-模拟ftp的目录状态显示
var http=require("http");
var fsp=require("fs/promises");
var path=require("path");
var {getData}=require("../Utils");
http.createServer(async (req,res)=>{
res.setHeader("Access-Control-Allow-Origin","*");
var data=await getData(req,res);
var list=await getFile(data);
if(!list){
res.end(JSON.stringify({err:"错误的路径"}));
return;
}
res.end(JSON.stringify({err:null,list}));
}).listen(4001);
async function getFile(data){
var stat;
await fsp.stat(data).then(_stat=>stat=_stat).catch(err=>stat=null);
if(!stat) return null;
var files=await fsp.readdir(data);
var list=[];
if(data!=="D:/"){
list.push({fileName:"..",path:data,size:0,file:false,cTime:0});
}
for(var i=0;i<files.length;i++){
var s;
await fsp.stat(path.join(data,files[i])).then(_stat=>s=_stat).catch(err=>s=null);
if(s){
list.push({fileName:files[i],path:data,size:s.size,file:s.isFile(),cTime:s.ctimeMs})
}
}
return list;
}
<!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>
<style>
.file{
background-image: url("./img/a.png");
width: 87px;
height: 70px;
transform: scale(0.3,0.3);
background-position-x: -110px;
background-position-y: -100px;
}
.dir{
background-image: url("./img/a.png");
width: 87px;
height: 70px;
transform: scale(0.3,0.3);
background-position-x: -500px;
background-position-y: -100px;
}
a{
text-decoration: none;
color: black;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th></th>
<th>名称</th>
<th>大小</th>
<th>修改日期</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
var table;
init();
function init() {
table = document.querySelector("tbody");
renderTable();
}
async function renderTable(path="D:/"){
var data = await getPathData(path);
if (!data.err) {
data.list.sort((a,b)=>{
return a.file-b.file;
})
// console.log(data.list);
table.innerHTML = data.list.reduce((value, item) => {
// console.log(item.path);
var methods=item.path+(item.path==="D:/" ? "" :"/")+item.fileName;
methods=`javascript:${(item.file ? "void(0)" : 'renderTable("'+methods+'")')}`
return value+`<tr><td><div class='${item.file ? "file" :"dir"}'></div></td><td><a href='${methods}'>${item.fileName}</a></td><td>${item.size}</td><td>${new Date(item.cTime).toLocaleString()}</td></tr>`
}, "")
} else {
console.log(data.err);
}
}
async function getPathData(path) {
var data = await fetch("http://localhost:4001", {
method: "POST",
body: path
});
data = await data.json();
return data;
}
</script>
</body>
</html>
'>
i
t
e
m
.
f
i
l
e
N
a
m
e
<
/
a
>
<
/
t
d
>
<
t
d
>
{item.fileName}</a></td><td>
item.fileName</a></td><td>{item.size}${new Date(item.cTime).toLocaleString()}`
}, “”)
} else {
console.log(data.err);
}
}
async function getPathData(path) {
var data = await fetch("http://localhost:4001", {
method: "POST",
body: path
});
data = await data.json();
return data;
}
</script>
```