Ajax
Ajax是异步的JavaScript和XML,简单点说,就是使用XMLHttpRequest对象与服务器通信,它可以使用JSON,XML,HTML和text文本格式发送和接收数据。Ajax最吸引人的就是它的“异步”特性,也就是说它可以在不重新刷新整个页面的情况下与服务器通信,交换数据或刷新部分内容。
1、什么是Ajax
Ajax = 异步 JavaScript 和 XML,是一种用于创建快速动态网页的技术,通过与后台服务器的少量数据交互实现页面的部分更新。
2、XMLHttpRequest
XMLHttpRequest对象用于与后台服务器进行数据交换,是Ajax的基础,目前所有的浏览器都支持XMLHttpRequest,所有浏览器均内建XMLHttpRequest对象。
-
创建XMLHttpRequest对象
const xhr = new XMLHttpRequest()
-
向服务器发送请求
//GET xhr.open("GET","/try/ajax/demo_get2.php?fname=Henry&lname=Ford",true); xhr.send(); //POST xhr.open("POST","/try/ajax/demo_post2.php",true); xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xhr.send("fname=Henry&lname=Ford");
其中 open 方法第一个参数是请求的类型:GET 或 POST ;第二个参数是 url 请求访问的地址;第三个参数是 async 是否异步操作。send 方法是将请求发送到服务器,里面的参数必须是 string 类型,用于 POST 请求。setRequestHeader 方法用于向请求添加HTTP头
使用 GET 还是 POST?
GET:更简单也更快,没有请求体条件限制
POST:没有数据量限制,更稳定也更可靠,能够更新服务器上的数据
URL:URL称为统一资源定位符,俗称网页地址,简称网址,是因特网上标准的资源的地址,用于访问网络资源,如同再网路上的门牌。
我们根据这个网址对URL进行分析http://hmajax.itheima.net/api/provice
- 协议
- http协议:是超文本传输协议(Hyper Text Transfer Protocol),规定浏览器和服务器之间传输数据的格式
- https协议:是超文本传输安全协议(Hypertext Transfer Protocol Secure )是 HTTP 的安全版本,它在 HTTP 下增加了 SSL/TLS 协议,提供了数据加密、完整性校验和身份验证。
- 域名
- hmajax.itheima.net,标记服务器在互联网中的方位
- 资源路径
- /api/province,标记资源在服务器下的具体位置
- 协议
-
服务器响应
我们在向后台发送了请求之后,如需要获取来自服务器的响应,就需要使用 XMLHttpRequest 对象的responseText 或 responseXML 属性。
//如果响应是 XML 属性就使用 responseXML,非 XML 属性就使用 responseText console.log(xhr.responseText) console.log(xhr.reponseXML)
3、回调地狱
XMLHttpRequest(XHR)对象用于与服务器交互,通过XMLHttpRequest可以在不刷新页面的情况下请求特定的URL,获取数据,者允许网页在不影响用户操作的情况下,更新页面的局部内容。
3.1、promise对象
Promise对象用于表示一个异步操作的最终完成或失败及其结果
好处:
1、逻辑更清晰
2、了解axios函数内部运作机制
3、能解决回调函数地狱问题
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('请求成功')
reject(new Error('请求失败'))
}, 2000)
})
p.then(result => {
console.log(result);
}).catch(error => {
console.log(error);
})
3.2、promise - 三种状态
一个promise对象,必然处于以下三种状态之一
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝
- 已兑现(fulfilled):意味着,操作成功完成
- 已拒绝(rejected):意味着,操作失败
promise对象一旦被兑现或拒绝,状态就已经无法再被改变了
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('method', 'url')
xhr.addEventListener('loadend', () => {
xhr.status >= 200 && xhr.status < 300 ? resolve(JSON.parse(xhr.response)) : reject(new Error(xhr.response))
})
xhr.send()
})
p.then(result => {
console.log(result);
}).catch(error => {
console.log(error);
})
3.3、回调函数地狱
在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱,缺点:可读性差,异常无法捕获,耦合性高。
解决方法:promise-链式调用
概念:依靠then()方法会返回一个新生成的promise对象特性,继续串联下一环任务,直到结束
细节:then()回调函数中的返回值,会影响新生成的promise对象最终状态和结果
好处:通过链式调用可以解决回调函数地狱问题
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
}).then(result => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('222')
}, 1000)
})
}).then(result => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('333')
}, 1000)
})
}).catch(error => {
console.log(error);
setTimeout(() => {
console.log('444')
}, 2000)
}).finally(() => {
setTimeout(() => {
console.log('555')
}, 1000)
})
3.4、async函数和await
async函数是使用async关键字声明的函数。async函数是啊AsyncFunction构造函数的实例,并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意的链式调用Promise
在async函数内,使用await关键字取代then函数,等待获取Promise对象成功状态的结果值
function testRequest() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
}
async function testAsync() {
try {
const re = await testRequest()
console.log(re);
console.log('Async');
} catch (error) {
// console.dir(error);
console.log(error);
}
}
testAsync()
3.5、promise.all静态方法
当一个Promise需要多个Promise对象完成为前提时,我们就需要合并多个Promise对象,当合并的Promise对象全都成功时才会触发.then(),任意一个Promise对象失败都会触发.catch()
const p = Promise.all([Promise对象, Promise对象, ......])
p.then(() => {
}).catch(() => {
})
4、总结
其实就目前的Ajax来看,我们就只需要做一个简单的了解一下底层内容即可,因为目前我们基本上很少使用原生的Ajax去进行数据的请求访问,主要是因为其安全性较低,容易被脚本和注入攻击、跨域限制、代码复杂等等问题导致Ajax被淘汰。目前都在使用 js + jQuery、vue + axios 和 fetch,其中vue + axios是相对与使用最多的框架,但他们的底层都是Ajax,是对Ajax的进一步简化封装。因此选择合适的网络请求框架对于开发有着很大的帮助。