Ajax
AJAX 就是用 JS 发送请求和接收响应
AJAX 是异步的 JS 和 XML(Asynchronous JavaScript And XML),目前我们一般使用 JSON 代替 XML。AJAX 主要用于在不刷新页面的情况下向浏览器发起请求并接受响应,最后局部更新页面,它最核心的概念是 XMLHttpRequest 对象,该对象可以发起 HTTP 请求,我们可以监听其 readyState 的变化获得响应。
你可以使用AJAX最主要的两个特性做下列事:
- 在不重新加载页面的情况下发送请求给服务器。
- 接受并使用从服务器发来的数据。
JS 中发送一个请求到成功得到响应的时间在几百毫秒到一两秒之间。
使用 AJAX 的四个步骤:
1. 创建 XMLHttpRequest 对象
通过XMLHttpRequest() 构造函数用于初始化一个 XMLHttpRequest 实例对象
var xhr = new XMLHttpRequest()
2.与服务器建立连接 调用对象的 open 方法 .open(method, url)
通过 XMLHttpRequest 对象的 open() 方法与服务器建立连接
xhr.open(method, url, [async][, user][, password])
参数说明:
method:表示当前的请求方式,常见的有GET、POSTurl:服务端地址async:布尔值,表示是否异步执行操作,默认为trueuser: 可选的用户名用于认证用途;默认为`nullpassword: 可选的密码用于认证用途,默认为`null
3. 监听对象的 onreadystatechange 事件(在事件处理函数里操作 CSS / JS / HTML / responseXML / JSON.parse)
onreadystatechange 事件用于监听服务器端的通信状态,主要监听的属性为XMLHttpRequest.readyState ,
关于XMLHttpRequest.readyState属性有五个状态,如下图显示
只要 readyState属性值一变化,就会触发一次 readystatechange 事件
XMLHttpRequest.responseText属性用于接收服务器端的响应结果
举个例子:
const request = new XMLHttpRequest()
request.onreadystatechange = function(e){
if(request.readyState === 4){ // 整个请求过程完毕
if(request.status >= 200 && request.status <= 300){
console.log(request.responseText) // 服务端返回的结果
}else if(request.status >=400){
console.log("错误信息:" + request.status)
}
}
}
request.open('POST','http://xxxx')
request.send()
4. 调用对象的 send 方法(发送请求)
通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端
xhr.send([body])
body: 在 XHR 请求中要发送的数据体,如果不传递数据则为 null
如果使用GET请求发送数据的时候,需要注意如下:
- 将请求数据添加到
open()方法中的url地址中 - 发送请求数据中的
send()方法中参数设置为null
加载
在设置正确的 Content-Type 的前提下,使用 AJAX 可以轻量级地请求 HTML / CSS / JavaScript / XML / JSON 等内容,只要知道怎么解析这些内容,就可以使用这些内容。解析方法如下:
- 得到 CSS 之后生成 style 标签
- 得到 JS 之后生成 script 标签
- 得到 HTML 之后使用 innerHTML 和 DOM API
- 得到 XML 之后使用 reponseXML 和 DOM API
- 得到 JSON 之后使用 JSON.parse
- 不同类型的数据有不同类型的解析方法
用 AJAX 加载 CSS
getCSS.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/style.css"); //readyState = 1
request.onreadystatechange = () => {
//下载完成,但不知道是成功(2xx) 还是失败(4xx 5xx)
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
//创建 style 标签
const style = document.createElement("style");
//填写 style 内容
style.innerHTML = request.response;
//插入到 head 里面
document.head.appendChild(style);
} else {
alert("加载 CSS 失败");
}
}
};
request.send(); //readyState = 2
};
用 AJAX 加载 JS
getJS.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/2.js");
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
//创建 script 标签
const script = document.createElement("script");
//填写 script 内容
script.innerHTML = request.response;
//插入到 body 里面
document.body.appendChild(script);
} else {
alert("加载 JS 失败");
}
}
};
request.send();
};
用 AJAX 加载 HTML
getHTML.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/3.html");
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
//创建 div 标签
const div = document.createElement("div");
//填写 div 内容
div.innerHTML = request.response;
//插入到 body 里面
document.body.appendChild(div);
} else {
alert("加载 HTML 失败");
}
}
};
request.send();
};
用 AJAX 加载 XML
getXML.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/4.xml");
request.onreadystatechange = () => {
if (
request.readyState === 4 &&
request.status >= 200 &&
request.status < 300
) {
//获取 XML 的 DOM 对象
const dom = request.responseXML;
//获取内容
const text = dom.getElementsByTagName("warning")[0].textContent;
//消除内容中的'回车'
console.log(text.trim());
}
};
request.send();
};
用 AJAX 加载 JSON
getJSON.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/5.json");
request.onreadystatechange = () => {
if (
request.readyState === 4 &&
request.status >= 200 &&
request.status < 300
) {
console.log(request.response);
const object = JSON.parse(request.response); //字符串转换为对象(反序列化)
console.log(object);
myName.textContent = object.name;
}
};
request.send();
};
学习链接
例子
封装
通过上面对XMLHttpRequest对象的了解,下面来封装一个简单的ajax请求
//封装一个ajax请求
function ajax(options) {
//创建XMLHttpRequest对象
const xhr = new XMLHttpRequest()
//初始化参数的内容
options = options || {}
options.type = (options.type || 'GET').toUpperCase()
options.dataType = options.dataType || 'json'
const params = options.data
//发送请求
if (options.type === 'GET') {
xhr.open('GET', options.url + '?' + params, true)
xhr.send(null)
} else if (options.type === 'POST') {
xhr.open('POST', options.url, true)
xhr.send(params)
//接收请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
let status = xhr.status
if (status >= 200 && status < 300) {
options.success && options.success(xhr.responseText, xhr.responseXML)
} else {
options.fail && options.fail(status)
}
}
}
}
使用方式如下
ajax({
type: 'post',
dataType: 'json',
data: {},
url: 'https://xxxx',
success: function(text,xml){//请求成功后的回调函数
console.log(text)
},
fail: function(status){////请求失败后的回调函数
console.log(status)
}
})
Promise
大佬文章 异步解决方案
什么是异步什么是同步
- 同步:如果能直接拿到结果就是同步
- 异步:不能直接拿到结果
异步举例
-
以AJAX为例
request.send()之后并不能直接得到response,必须等到readystate变为4之后,浏览器才会回头调用request.onreadystatechange函数。
-
回调callback
写给自己用的函数,不是回调,写给别人用的函数是回调。比如request.onreadystatechange就是我写给浏览器调用的函数。
异步和回调的关系
-
关联
异步任务需要在得到结果时通知js来取,这时我们可以给js留一个函数地址,异步任务完成时浏览器调用该函数地址,同时把结果作为参数传给该函数,这里的函数是我写给浏览器调用的,所以时回调函数。
-
区别
异步任务需要用到回调函数来通知结果 但回调函数不一定只用在异步任务里,也可以用到同步任务中 arr.forEach(n=>console.log(n)) 就是同步回调
判断同步异步
-
如果一个函数的返回值处于
1.setTimeout
2.AJAX(即XMLHttpRequest)
3.addEventListener 这三个值的内部就是异步函数。
注意:不要把AJAX设置成同步的,这样会使页面卡住
总结
- 异步任务不能拿到结果
- 于是传一个回调给异步任务
- 异步完成时调用回调
- 调用时把结果作为参数
promise(解决异步任务的两个结果:成功或失败)
解决异步任务的回调问题
- 规范回调的名字或顺序
- 拒绝回调地狱,让代码的可读性更高
- 很方便的捕获任务
以AJAX为例解释promise
核心就是 这一句话
总结
-
第一步
1.return new Promise((resolve,reject)=>{...})
2.任务成功调用resolve(result)
3.任务失败调用reject(onerror)
4.resolve和reject会再去调用成功和失败函数
-
第二步
使用.then(success,fail)传入成功和失败函数
封装AJAX的缺点
- .post无法上传数据(request.send可以上传)
- 不能设置请求头(request.setRequestHeader(key,value))
解决方法
-
jQuery.ajax
-
axios(目前最新的ajax库)
代码示例
优点:自动调用JSON.parse,请求拦截器;响应拦截器
Promise的使用
第一步
创建一个promise对象、可以使用new来调用Promise的构造器来进行实例化
return new Promise((resolve,reject)=>{
// 异步处理
// 处理结束后、调用resolve 或 reject
})
- 任务成功时调用
resolve(成功)任务失败时调用reject(失败) - resolve 和 reject 都只接受一个参数
第二步
第一步构造出来的promise对象,含有一个 .then() 函数属性使用promise.then() 实例方法,设置其值在 resolve(成功) / reject(失败)时调用的回调函数
promise.then(onFulfilled, onRejected)
-
resolve(成功)时
onFulfilled会被调用 -
reject(失败)时
onRejected会被调用
举例
使用promise来发送网络请求
function getURL(URL) {
return new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', URL, true);
req.onload = function () {
if (req.status === 200) {
resolve(req.responseText);
} else {
reject(req.statusText));
}
};
req.onerror = function () {
reject(req.statusText));
};
req.send();
});
}
var URL = "http://xxx";
getURL(URL).then(function onFulfilled(value){
console.log(value);
},function onRejected(error){
console.log(error);
});
Promise还有更高级的用法,链式调用等等,以后在进行总结~