文章目录
- HTTP
- 请求报文
- 响应报文
- 常见的状态码
- readyState 属性
- 原生AJAX
- AJAX 简介
- XML 简介
- AJAX 的特点
- AJAX 的使用
- 解决 IE 缓存问题
- ajax返回的状态
- jQuery-AJAX
- get 请求
- post 请求
- ajax 请求
- Axios-AJAX
- get 请求
- post 请求
- ajax 请求
- Fetch-AJAX
- 跨域
- 同源策略
- 如何解决跨域
- JSONP
- CORS
- 所使用的node服务代码
- Web Socket
HTTP
HTTP(hypertext transport protocol)协议『超文本传输协议』,协议详细规定了浏览器和万维网服务器之间互相通信的规则。
请求报文
重点是格式与参数
行 POST /s?ie=utf-8 HTTP/1.1
头 Host: atguigu.com
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行
体 username=admin&password=admin
响应报文
行 HTTP/1.1 200 OK
头 Content-Type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
体 <html>
<head>
</head>
<body>
<h1>尚硅谷</h1>
</body>
</html>
常见的状态码
- 1XX:指定客户端相应的某些动作
- 2XX:成功
- 3XX:已经移动的文件并且被包含在定位头信息中定心的地址信息(重定向,为了完成请求,必需执行的动作)
- 4XX:客户端错误
- 5XX:服务器错误
- 404:找不到文件
- 403:服务器已经得到请求,但是拒绝执行
- 401:当前请求需要用户验证
- 400:请求无效
- 500:服务器内部问题
- 200:请求成功
- 304:未修改,所请求的资源未修改
readyState 属性
- 0:未初始化(Uninitialized)。尚未调用 open()方法。
- 1:已打开(Open)。已调用 open()方法,尚未调用 send()方法。
- 2:已发送(Sent)。已调用 send()方法,尚未收到响应。
- 3:接收中(Receiving)。已经收到部分响应。
- 4:完成(Complete)。已经收到所有响应,可以使用了
原生AJAX
AJAX 简介
- AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。
- 异步:不会占用js的主线程,而是去调用线程池的子线程(网络请求线程)
- 实现的语法主要是JavaScript
- xml:属于html的兄弟。由于它的解析实在是过于麻烦,所有现在逐渐被json代替
- 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
- AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
XML 简介
- XML 可扩展标记语言。
- XML 被设计用来传输和存储数据。
- XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签,
- 全都是自定义标签,用来表示一些数据。
比如说我有一个学生数据:name = "孙悟空" ; age = 18 ; gender = "男" ;
// 用 XML 表示:
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
// 用 JSON 表示:
{"name":"孙悟空","age":18,"gender":"男"}
现在已经基本被 JSON 取代了。
AJAX 的特点
AJAX 的优点
- 可以无需刷新页面而与服务器端进行通信。
- 允许你根据用户事件来更新部分页面内容。
AJAX 的缺点
- 没有浏览历史,不能回退
- 存在跨域问题(同源)
- SEO 不友好
AJAX 的使用
核心对象:XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的
// 1) 创建 XMLHttpRequest 对象
let xhr = null;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
//设置响应体数据的类型
xhr.responseType = 'json';
//超时设置 2s 设置
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert("网络异常, 请稍后重试!!");
}
//网络异常回调
xhr.onerror = function(){
alert("你的网络似乎出了一些问题!");
}
// 2) 设置请求信息
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 3) 发送请求
xhr.send(body) //get 请求不传 body 参数,只有 post 请求使用
// 4) 接收响应
//xhr.responseXML 接收 xml 格式的响应数据
//xhr.responseText 接收文本格式的响应数据
//JSON.parse(xhr.response) 将json文件转换为js数据
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText); // 作为响应体返回的文本
} else {
console.log("Request was unsuccessful: " + xhr.status); // 请求失败,返回 响应的 HTTP 状态
}
}
};
// 取消请求:xhr.abort();
// get请求参数拼接方法
const addURLParam = (url, name, value) => {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
// post表单传参数
let form = document.getElementById("user-info");
xhr.send(new FormData(form));
一般就写1~4步即可
解决 IE 缓存问题
问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩
余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址
即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now());
ajax返回的状态
- 0:(未初始化)还没有调用send()方法
- 1:(载入)已调用send()方法,正在发送请求
- 2:(载入完成)send()方法执行完成,已接受到全部的响应内容
- 3:(交互)正在解析响应内容
- 4:(完成)响应内容解析完成,可在客户端调用了
jQuery-AJAX
get 请求
$.get(url, [data], [callback], [type])
- url:请求的 URL 地址。
- data:请求携带的参数。
- callback:载入成功时回调函数。
- type:设置返回内容格式,xml, html, script, json, text, _default
post 请求
$.post(url, [data], [callback], [type])
- url:请求的 URL 地址。
- data:请求携带的参数。
- callback:载入成功时回调函数。
- type:设置返回内容格式,xml, html, script, json, text, _default
ajax 请求
$.ajax({
//url
url: 'http://127.0.0.1:8000/jquery-server',
//参数
data: {a:100, b:200},
//请求类型
type: 'GET',
//响应体结果
dataType: 'json',
//成功的回调
success: function(data){
console.log(data);
},
//超时时间
timeout: 2000,
//失败的回调
error: function(){
console.log('出错啦!!');
},
//头信息
headers: {
c:300,
d:400
}
});
Axios-AJAX
更详细的参考React 中使用 axios
get 请求
//默认配置
axios.defaults.method = 'GET';//设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000';//设置基础 URL
axios.defaults.params = {id:100};
axios.defaults.timeout = 3000;//
//配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
axios.get('/axios-server', {
//url 参数
params: {
id: 100,
vip: 7
},
//请求头信息
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value);
});
// 取消请求:cancel();
post 请求
//配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
axios.post('/axios-server', {
username: 'admin',
password: 'admin'
}, {
//url
params: {
id: 200,
vip: 9
},
//请求头参数
headers: {
height: 180,
weight: 180,
}
});
ajax 请求
// 传统方式
axios({
methods: '请求方式',
url: '请求地址',
params: { // get
参数名: 参数值
},
data: { // post put patch
参数名: 参数值
}
})
.then(res => { // 请求成功后的处理
// res是服务器返回的响应数据
})
.catch(err => { // 请求失败后的处理
// err是请求失败后的信息
})
// get请求
axios.get("url", {params: {参数名: 参数值}})
.then(res => {
})
.catch(err => {
})
// post请求:发送表单数据和文件上传
axios.post("url", {参数名: 参数值})
.then(res => {
}).catch(err => {
})
// put请求:对数据进行全部更新
axios.put("url", {参数名: 参数值})
.then(res => {
}).catch(err => {
})
// patch请求:只对更改过的数据进行更新
axios.patch("url", {参数名: 参数值})
.then(res => {
}).catch(err => {
})
// delete请求:删除请求(参数可以放在url上,也可以和post一样放在请求体中)
axios.delete('url', {
params: {
参数名: 参数值
}
}).then(res => {
}).catch(err => {
})
axios.delete('url', {data: {参数名: 参数值}})
.then(res => {
})
.catch(err => {
})
Fetch-AJAX
fetch('http://127.0.0.1:8000/fetch-server?vip=10', {
//请求方法
method: 'POST',
//请求头
headers: {
name:'atguigu'
},
//请求体
body: 'username=admin&password=admin'
}).then(response => {
// return response.text();
return response.json();
}).then(response=>{
console.log(response);
});
跨域
同源策略
同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。
同源: 协议、域名、端口号 必须完全相同。
违背同源策略就是跨域。
如何解决跨域
JSONP
JSONP 是什么
JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明
才智开发出来,只支持 get 请求
JSONP 怎么工作的?
在网页有一些标签天生具有跨域能力,比如:img link iframe script。 JSONP 就是利用 script 标签的跨域能力来发送请求
JSONP 的使用
// 1.动态的创建一个 script 标签
var script = document.createElement("script");
// 2.设置 script 的 src,设置回调函数
script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data) {
alert(data.name);
};
// 3.将 script 添加到 body 中
document.body.appendChild(script);
// 4.服务器中路由的处理
router.get("/testAJAX" , function (req , res) {
console.log("收到请求");
var callback = req.query.callback;
var obj = {
name:"孙悟空",
age:18
}
res.send(callback+"("+JSON.stringify(obj)+")");
});
jQuery-jsonp
$.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data){
$('#result').html(`
名称: ${data.name}<br>
校区: ${data.city}
`)
});
CORS
CORS 是什么?
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
CORS 怎么工作的?
CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应
以后就会对响应放行。
CORS 的使用
// 主要是服务器端的设置:
router.get("/testAJAX" , function (req , res) {
//通过 res 来设置响应头,来允许跨域请求
//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
res.set("Access-Control-Allow-Origin","*");
res.send("testAJAX 返回的响应");
});
所使用的node服务代码
//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();
//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO AJAX - 2');
});
//可以接收任意类型的请求
app.all('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头
response.setHeader('Access-Control-Allow-Headers', '*');
//设置响应体
response.send('HELLO AJAX POST');
});
//JSON 响应
app.all('/json-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头
response.setHeader('Access-Control-Allow-Headers', '*');
//响应一个数据
const data = {
name: 'atguigu'
};
//对对象进行字符串转换
let str = JSON.stringify(data);
//设置响应体
response.send(str);
});
//针对 IE 缓存
app.get('/ie', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO IE - 5');
});
//延时响应
app.all('/delay', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
setTimeout(() => {
//设置响应体
response.send('延时响应');
}, 1000)
});
//jQuery 服务
app.all('/jquery-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
// response.send('Hello jQuery AJAX');
const data = {name:'尚硅谷'};
response.send(JSON.stringify(data));
});
//axios 服务
app.all('/axios-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
// response.send('Hello jQuery AJAX');
const data = {name:'尚硅谷'};
response.send(JSON.stringify(data));
});
//fetch 服务
app.all('/fetch-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
// response.send('Hello jQuery AJAX');
const data = {name:'尚硅谷'};
response.send(JSON.stringify(data));
});
//jsonp服务
app.all('/jsonp-server',(request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
name: '尚硅谷atguigu'
};
//将数据转化为字符串
let str = JSON.stringify(data);
//返回结果
response.end(`handle(${str})`);
});
//用户名检测是否存在
app.all('/check-username',(request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
exist: 1,
msg: '用户名已经存在'
};
//将数据转化为字符串
let str = JSON.stringify(data);
//返回结果
response.end(`handle(${str})`);
});
//
app.all('/jquery-jsonp-server',(request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
name:'尚硅谷',
city: ['北京','上海','深圳']
};
//将数据转化为字符串
let str = JSON.stringify(data);
//接收 callback 参数
let cb = request.query.callback;
//返回结果
response.end(`${cb}(${str})`);
});
app.all('/cors-server', (request, response)=>{
//设置响应头
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", '*');
response.setHeader("Access-Control-Allow-Method", '*');
// response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
response.send('hello CORS');
});
//4. 监听端口启动服务
app.listen(8000, () => {
console.log("服务已经启动, 8000 端口监听中....");
});
Web Socket
Web Socket(套接字)的目标是通过一个长时连接实现与服务器全双工、双向的通信。在 JavaScript
中创建 Web Socket 时,一个 HTTP 请求会发送到服务器以初始化连接。服务器响应后,连接使用 HTTP
的 Upgrade 头部从 HTTP 协议切换到 Web Socket 协议。这意味着 Web Socket 不能通过标准 HTTP 服务
器实现,而必须使用支持该协议的专有服务器。
因为 Web Socket使用了自定义协议,所以 URL方案(scheme)稍有变化:不能再使用 http://或 https://,
而要使用 ws://和 wss://。前者是不安全的连接,后者是安全连接。在指定 Web Socket URL 时,必须包
含 URL 方案,因为将来有可能再支持其他方案。
使用自定义协议而非 HTTP 协议的好处是,客户端与服务器之间可以发送非常少的数据,不会对
HTTP 造成任何负担。使用更小的数据包让 Web Socket 非常适合带宽和延迟问题比较明显的移动应用。
使用自定义协议的缺点是,定义协议的时间比定义 JavaScript API 要长。Web Socket 得到了所有主流浏
览器支持
// 创建WebSocket
let socket = new WebSocket("ws://www.example.com/server.php");
// readyState 属性表示当前状态。
// - WebSocket.OPENING(0):连接正在建立。
// - WebSocket.OPEN(1):连接已经建立。
// - WebSocket.CLOSING(2):连接正在关闭。
// - WebSocket.CLOSE(3):连接已经关闭。
// 发送数据
let stringData = "Hello world!"; // 字符串
let arrayBufferData = Uint8Array.from(['f', 'o', 'o']); // ArrayBuffe
let blobData = new Blob(['f', 'o', 'o']); // Blob
socket.send(stringData);
socket.send(arrayBufferData.buffer);
socket.send(blobData);
// 接受数据
socket.onmessage = function(event) {
let data = event.data;
// 对数据执行某些操作
};
// 在连接成功建立时触发
socket.onopen = function() {
alert("Connection established.");
};
// 在发生错误时触发。连接无法存续
socket.onerror = function() {
alert("Connection error.");
};
// 在连接关闭时触发
socket.onclose = function() {
alert("Connection closed.");
};