一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
一. 客户端与服务器
服务器:上网过程中,负责存放和对外提供资源的电脑,叫做服务器。
客户端:上网过程中,负责获取和消费资源的电脑,叫做客户端。
二. URL地址
URL(全称是UniformResourceLocator)中文叫统一资源定位符,用于标识互联网上每个资源的唯一存放位置。浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源。 常见的URL举例:
URL地址一般由三部组成:
① 客户端与服务器之间的通信协议
② 存有该资源的服务器名称
③ 资源在服务器上具体的存放位置
图解客户端与服务器的通信过程
基于浏览器的开发者工具分析通信过程
- 打开 Chrome 浏览器
- Ctrl+Shift+I 打开 Chrome 的开发者工具
- 切换到 Network 面板
- 选中 Doc 页签
- 刷新页面,分析客户端与服务器的通信过程
网页中如何请求数据
- 数据,也是服务器对外提供的一种资源。只要是资源,必然要通过 请求 – 处理 – 响应 的方式进行获取。
如果要在网页中请求服务器上的数据资源,则需要用到 XMLHttpRequest 对象。XMLHttpRequest(简称 xhr)是浏览器提供的 js 成员,通过它,可以请求服务器上的数据资源。 最简单的用法 var xhrObj = new XMLHttpRequest()
资源的请求方式
客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为 get 和 post 请求。
-
get 请求通常用于获取服务端资源(向服务器要资源) 例如:根据 URL 地址,从服务器获取 HTML 文件、css 文件、js文件、图片文件、数据资源等
-
post 请求通常用于向服务器提交数据(往服务器发送资源) 例如:登录时向服务器提交的登录信息、注册时向服务器提交的注册信息、添加用户时向服务器提交的用户信息等各种数据提交操作
Ajax
- Ajax 的全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)。
通俗的理解:在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式,就是Ajax。AJAX全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据,用户体验更好。
XML 简介
-
XML 可扩展标记语言。被设计用来传输和存储数据。
-
XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据。
比如说我有一个学生数据:
name = "孙悟空" ; age = 18 ; gender = "男" ;
用 XML 表示:
孙悟空
18
男
现在已经被 JSON 取代了。
用 JSON 表示:
{"name":"孙悟空","age":18,"gender":"男"}
AJAX 的优点
1)可以无需刷新页面而与服务器端进行通信。
2)允许你根据用户事件来更新部分页面内容。
AJAX 的缺点
1)没有浏览历史,不能回退
2)存在跨域问题(同源)
3)SEO 不友好
HTTP
(1)请求报文:
- 请求行:Get/Post + 参数字符串 + http版本
- 请求头: Host: Cookie: Content-type: User-Agent: 空行
- 体 (GET为空)、post可以不为空
(2)响应报文:
-
行:http版本 + 状态码 + 响应状态字符串
-
头: Content-Type: Content-Length: Content-encoding:
空行 -
体 html文本
AJAX 的使用
核心对象XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的。
使用步骤
1)创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
2)设置请求信息
xhr.open(method, url); 例如: xhr.open('GET','http://localhost:8000/server');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//可以设置请求头,一般不设置
3)发送请求
xhr.send(body) //get 请求不传 body 参数,只有 post 请求使用
4)接收响应
//xhr.responseXML
接收 xml 格式的响应数据
//xhr.responseText
接收文本格式的响应数据
xhr.onreadystatechange = function (){
if(xhr.readyState == 4 && xhr.status == 200){
var text = xhr.responseText;
console.log(text);
}
}
readystate:
0:表示 XMLHttpRequest 实例已经生成,但是 open()方法还没有被调用。
1:表示 send()方法还没有被调用,仍然可以使用 setRequestHeader(),设定 HTTP请求的头信息。
2:表示 send()方法已经执行,并且头信息和状态码已经收到。
3:表示正在接收服务器传来的 body 部分的数据。
4:表示服务器数据已经完全接收,或者本次接收已经失败了
get方式 url参数设置
xhr.open('GET', 'http://localhost:8000/server?a=100&b=200&c=300');
post方式 url参数设置
xhr.send('a=100&b=200&c=300');
设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
自定义请求头
对应(server.js): //响应头
response.setHeader('Access-Control-Allow-Headers', '*');
(类型)
JSON响应数据设置
(1)(html)
添加语句
//设置响应体数据的类型 xhr.responseType = 'json';
text.innerHTML = xhr.response.name;
(2)server.js:
解决IE缓存(数据更新不及时)问题
更改为(?t=' + Date.now())
xhr.open('GET', 'http://localhost:8000/ie?t=' + Date.now());
超时解决
(模拟时设置server.js超时)
中断请求
核心代码
xhr.abort();
API总结
- XMLHttpRequest():创建 XHR 对象的构造函数
- status:响应状态码值,如 200、404
- statusText:响应状态文本,如 ’ok‘、‘not found’
- readyState:标识请求状态的只读属性 0-1-2-3-4
- onreadystatechange:绑定 readyState 改变的监听
- responseType:指定响应数据类型,如果是 ‘json’,得到响应后自动解析响应
- response:响应体数据,类型取决于 responseType 的指定
- timeout:指定请求超时时间,默认为 0 代表没有限制
- ontimeout:绑定超时的监听
- onerror:绑定请求网络错误的监听
- open():初始化一个请求,参数为:(method, url[, async])
- send(data):发送请求
- abort():中断请求 (发出到返回之间)
- getResponseHeader(name):获取指定名称的响应头值
- getAllResponseHeaders():获取所有响应头组成的字符串
- setRequestHeader(name, value):设置请求头
jQuery 中的AJAX
1 get 请求
$.get(url, [data], [callback], [type])
- url:请求的URL 地址
- data:请求携带的参数
- callback:载入成功时回调函数
- type:设置返回内容格式,xml, html, script, json, text, _default
2 post 请求
$.post(url, [data], [callback], [type])
- url:请求的URL 地址
- data:请求携带的参数
- callback:载入成功时回调函数
- type:设置返回内容格式,xml, html, script, json, text, _default
3.通用方法
$.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
}
})
补充:快速引入Jquery
(1)bootcdn
(2)搜索jquery
(3)cookie报错解决方法
axios
//配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btns[0].onclick = function() {
//GET 请求
axios.get('/axios-server', {
//url 参数
params: {
id: 100,
vip: 7
},
//请求头信息
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value);
});
}
btns[1].onclick = function() {
axios.post('/axios-server', {
//请求体
username: 'admin',
password: 'admin'
}, {
//url 参数
params: {
id: 200,
vip: 9
},
//请求头参数
headers: {
height: 180,
weight: 180,
}
});
}
btns[2].onclick = function() {
axios({
//请求方法
method: 'POST',
//url
url: '/axios-server',
//url参数
params: {
vip: 10,
level: 30
},
//头信息
headers: {
a: 100,
b: 200
},
//请求体参数
data: {
username: 'admin',
password: 'admin'
}
}).then(response => {
//响应状态码
console.log(response.status);
//响应状态字符串
console.log(response.statusText);
//响应头信息
console.log(response.headers);
//响应体
console.log(response.data);
})
}
fetch
跨域问题
1、同源策略与跨域
同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。 如果两个 URL (格式为:protocol://host:port)的 protocol(协议)、port(端口) (如果有指定的话)和 host(主机IP地址) 都相同的话,则这两个 URL 是同源。相关详细描述可参看官方MDN文档。
参考:浏览器的同源策略 - Web 安全 | MDN 、用JSONP解决跨域问题 JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持 get 请求。
JOSNP
1、实现原理
在网页有一些标签天生具有跨域能力,比如:img、link、iframe、script。JSONP 就是利用 script 标签的跨域能力来发送请求的。
当我们在网页中插入 script 标签时,即使 src 属性中所只指向的资源地址与当前网页是跨域的,也能正确执行 src 中的代码。
而 JSONP 正是利用了这一点,在后端代码中返回一个函数的调用(准确的说,返回的应该是一段浏览器能够解析的JS代码),当然,这个函数必须事先已经在前端代码中声明过了,同时传递给该函数的参数就是我们想要返回的数据。
<!-- 前端代码 -->
<script>
// 处理数据的函数,注意前端一定要实现声明这个函数,否则下方的script标签返回的代码将没法执行
function handle(data) {
//获取 result 元素
const result = document.getElementById('result');
result.innerHTML = data.name;
}
</script>
<!-- 向后端请求数据 -->
<script src="http://127.0.0.1:8000/jsonp-server"></script>
// 后端代码 server.js
// jsonp服务
app.all('/jsonp-server', (request, response) => {
// response.send('console.log("hello jsonp")');
// data是我们想要给前端返回的数据
const data = {
name: '尚硅谷atguigu'
};
// 将数据转化为字符串
let str = JSON.stringify(data);
// 返回结果,注意这里返回的是一个函数调用,其中的str参数才是我们想要返回的数据
response.end(`handle(${str})`);
});
2、JSONP实践——检测用户名是否存在
在一个输入框中输入用户名,当输入框失去焦点时向服务端发送AJAX请求,让服务端校验该用户名是否已经存在,并返回校验结果。前端声明一个 handle() 函数来对返回的结果进行处理。
// 后端代码 server.js
// 用户名检测是否存在
app.all('/check-username', (request, response) => {
// response.send('console.log("hello jsonp")');
const data = {
exist: 1,
msg: '用户名已经存在'
};
// 将数据转化为字符串
let str = JSON.stringify(data);
// 返回结果,注意这里返回的是一个函数调用,其中的str参数才是我们想要返回的数据
response.end(`handle(${str})`);
});
<!-- 前端代码 -->
<script>
// 获取 input 元素
const input = document.querySelector('input');
const p = document.querySelector('p');
// 声明 handle 函数用于处理服务端的响应结果
function handle(data){
input.style.border = "solid 1px #f00";
// 修改 p 标签的提示文本
p.innerHTML = data.msg;
}
// 给输入框绑定失去焦点事件
input.onblur = function(){
// 获取用户的输入值
let username = this.value;
// 向服务器端发送请求 检测用户名是否存在
// 1. 创建 script 标签
const script = document.createElement('script');
// 2. 设置标签的 src 属性
script.src = 'http://127.0.0.1:8000/check-username';
// 3. 将 script 插入到文档中
document.body.appendChild(script);
}
</script>
用CORS解决跨域问题
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
官方MDN文档是这样描述的:
CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。
同源安全策略 默认阻止“跨域”获取资源。但是 CORS 给了web服务器这样的权限,即服务器可以选择,允许跨域请求访问到它们的资源。
其他详细说明请参考:CORS - 术语表 | MDN
简单来说,CORS 是通过设置一个响应头 Access-Control-Allow-Origin 来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
用 CORS 解决跨域问题只需要在服务端代码中通过 response.setHeader() 方法进行相应的响应头设置。客户端正常发送请求即可,不需要做相应的设置。
// 后端代码 server.js
app.all('/cors-server', (request, response) => {
//设置响应头
// response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
response.setHeader("Access-Control-Allow-Origin", "*");
response.send('hello CORS');
});
如果服务端不设置 Access-Control-Allow-Origin 的话,一旦发生跨域问题就会报以下的错误:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/cors-server' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.