详细了解HTTP协议、promise、ajax和get、post、axios的关系并尝试封装promise;
ajax的字面意思是异步的JavaScript和XML,它不是一种新的技术规范,而是将异步的js和存储、传输数据的XML结合在一起使用的一种技术;只不过随着技术的发展存储、传输数据的JSON逐渐的把XML给取代了;
如果想搞清楚这几个概念之间的关系,我们要从前后端数据交互说起。
通常客户端向后端发送请求,后端接收到请求后把后端的数据返回给前端;前端向后端发送请求是通过XHLHttpRquest对象实例实现的,但是前端不能随便把什么杂乱无章的数据都往后端传递,否则后端就无法识别这些前端传递来的数据;为了避免前后端之间这种鸡同鸭讲的问题出现,我们就要求前后端在进行数据交互的时候必须遵守http协议规则--请求报文和响应报文;那么怎么将http协议的规则信息写入前后端的请求中呢?
我们可以通过XHLHttpRques对象实例拥有的一些内置的方法和属性把http协议规定的信息写入请求报文中,同时后端也有相应的响应对象实例把响应报文信息写入响应中;
“GET"、"POST"等是XHLHttpRquest对象实例的open()方法的一个参数,用来指定请求方法的类型,而小写的方法名"get"、"post"等是我们自己封装的ajax的方法名;
在es6之前,我们封装的ajax都是通过回调函数的方式来处理后端返回的数据,但是这会出现一个“回调地狱”的问题,es6为了解决这个问题就增加了promise来解决这个“回调地狱”的问题;promise采用是链式回调的方式,很好的解决了“回调地狱”的问题,promise当异步执行结束后会触发then()、catch();
axios是基于promise封装的ajax库;
ajax学习笔记:
ajax字面意思是异步的js和xml;它不是一种新的语言,而是将现有的标准组合早一起使用的新方式;
Xml是一种可拓展的标记语言;被设计用来传输和存储数据的;没有预定义标签,都是自定义标签;
Html是一种超文本标记语言;被设计用来显示数据的;只有预定义标签,不能自定义标签;
Ajax的优缺点:
优点:通过获取向后端请求的数据来实现页面的局部刷新,而不需要刷新整个页面;
缺点:没有浏览历史,不能回退;
存在默认无法跨域的问题;
Seo不友好;
http协议:超文本传输协议,是一种前后端进行数据交互的规范约定;
请求报文:
行:请求类型 / 请求路径|?请求参数 / 协议版本HTTP/1.1
注释:请求路径中的参数非必填项;
协议版本分为1.0和2.0;
头:Host: atguigu.com
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行:
体:suername=admin&password=admin
响应报文:
行:HTTP/1.1 200 0K
头:Content-Type:text/html;charset=utf-8
Content-length:2048
Content-encoding:gzip
空行:
体:<html>
<head>
</head>
<body>
<h1>尚硅谷</h1>
</body>
</html>
ajax操作步奏:
注意:ie浏览器对http请求的结果有缓存的作用,可以通过传递不同的参数来实现重新请求;
- 创建请求对象
Const xhr = new XHLHttpRequest();
Xhr.timeout=2000;超时设置2s,超过两秒请求会自动取消;
Xhr.ontimeout=function(){ //超时回调函数
Alert(“网络异常,请稍后重试”);
}
Xhr.onerror=function(){网络异常回调
Alert(“你的网络似乎出现了一些问题”)
}
xhr.responseType=”json”;自动把json 格式的数据转化为对象格式;
- 初始化请求对象
Xhr.open(‘GET’,’http://127.0.0.1:8000/server?a=100&b=200’),GET请求可以通过地址栏传参;
或者
Xhr.open(‘POST’,’http://127.0.0.1:8000/server)
设置请求头,
Xhr.setRequestHeader(“Content-type”,”application/x-www-form-urlencoded”)//用来设置请求体的类型
Xhr.setRequestHeader(“name”,”zhangsan”)//自定义头,需要后端设置允许接受自定义头信息
- 发送请求对象
Xhr.send();
或者
Post请求的话可以通过Xhr.send(“a=1&b:2&345”)方式传参,参数只要是字符串类型就行,但是要让后端能够接受识别并能够处理;
- 请求对象的事件绑定,处理后端返回的json字符串格式数据结果,需要通过json.parse()或者xhr.responseType=”json”转化之后才能使用;
Xhr.onreadystatechange=function(){
If(xhr.readyState===4){
If(300>xhr.status>=200){
Console.log(xhr.status)状态码
Console.log(xhr.statusText)状态字符串
Console.log(xhr.getAllResponseHeaders())所有响应头
Console.log(xhr.response)响应体
}
}
}
Xhr.abort()//在http请求发送后返回之前,可以取消http请求;
后端步奏:
- 引入express
Const express = require(“express”);
- 创建应用对象
Const app = express();
- 创建路由规则(也就是根据指定端口下的不同的请求路径,做出相应的响应的数据返回)
Request是对请求报文的封装;
Response是对响应报文的封装;
App.get(‘/serve’,(request,response)=>{
设置响应头,设置允许跨域
Response.setHeader(‘Access-Control-Allow-Origin’,’*’);
设置允许接受所有的请求头信息,会发一个option请求校验是否头部可用,后端要用all方法接受才行;
Response.setHeader(‘Access-Control-Allow-Headers’,’*’);
设置响应体
Response.send(“hello ajax”)//只能向前端发送json字符串格式的数据,如果是对象等格式的话,要转化为json字符串格式之后再发送给前端;
})
- 监听端口启动服务(监听指定端口,并在黑屏终端给出提示信息)
App.listen(8000,()=>{
Console.log(“服务已经启动,8000端口监听中。。。。。。”);
})
Axios:
Axios.defaults.baseURL = ‘http://127.0.0.1:8000’;设置默认路径端口;设置后请求路径可以省略此部分;
Fetch()方法是全局对象的一个方法,用于发起获取资源的请求,有点类似于axios的功能,它返回一个promise;
跨域:
同源:协议、域名、端口号必须保持一致;如果违背同源策略就是跨域;
因为单台服务器是有上限的,当遇到高并发的情况时要通过增加服务器来缓解高并发的压力,所以在不同服务器之间请求数据时就出现了跨域问题;
在同源策略下浏览器会给请求自动加上协议、域名和端口号,所以在请求的时候只需要写路由名就好;
跨域的解决方案:
- JSONP(非官方方案)是通过一些标签<script>、<img><link><iframe>等本身就有跨域请求的功能,所以可以通过这些标签夹带着参数去进行一些跨域的请求,然后后端需要进行相应的处理;
- CORS,跨域资源共享方案,是官方的跨域解决方案;
后端只需要设置: Response.setHeader(‘Access-Control-Allow-Origin’,’*’);
参照:https://blog.csdn.net/qq_46034886/article/details/104720359
https://www.cnblogs.com/lvdabao/p/es6-promise-1.html