ajax
1. AJAX在IE中的问题
1.1. XMLHttpRequest 对象IE兼容问题
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
var xhr;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xhr=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
1.2. AJAX在IE中的缓存问题
在默认情况下,IE会缓存相同地址ajax请求的结果。IE的第一次ajax请求会发送到服务器端处理,如果后续的请求的参数与第一次的一样,浏览器会直接返回缓存的结果而不是去服务器获取。有时候我们希望获取实时的数据,那么该如何解决这个问题呢?只要在ajax请求中加一个时间戳参数或随机参数就可以了。
console.log(Math.random());
console.log(new Date().getTime());
xhr.open('GET', './demo.txt?t=' + (new Date().getTime()), true)
2. 封装AJAX的GET请求
昨天我们学习了ajax的GET请求和POST请求,我们发现要实现一个ajax请求有五步操作,如果我们频繁的需要发送ajax请求,那么需要重复的去写着五步操作,显得很冗余,那么我们可不可以尝试着自己封装一下ajax的GET请求.
2.1. AJAX请求的五步操作:
// 1.创建一个异步对象
var xhr = new XMLHttpRequest()
// 2.(为异步对象)设置请求方式和请求地址
// open(method, url, async) async:true(异步) ajax 的意义就是异步,永远传true
xhr.open('GET', 'http://127.0.0.1:3030', true)
// 3.发送请求
xhr.send();
// 4.监听状态变化(调用回调函数代表请求完成了)
xhr.onreadystatechange = function () {
// xhr.readyState判断请求是否完成
if (xhr.readyState === 4) {
// xhr.status判断是否拿到了数据
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
// 5.处理返回的结果
console.log(xhr.response);
} else {
console.log('没有接收到服务器的数据');
}
}
}
2.2. 处理参数问题
通过观察我们可以发现,如果我们要发送多个请求,这五步的大部分代码我们是不会改变的,需要改变的有
1.URL,请求地址是不固定的
2.GET请求传递的参数是不固定的
3.请求成功后如何处理数据,
4.请求失败后如何处理这三块需要变动
还需要解决的问题有IE浏览器的兼容问题
2.3. 处理IE兼容问题
根据以上问题:我们可以把不固定的内容用参数的方式传入,IE浏览器的兼容问题直接复制在里面即可
function obj_str(obj) {
obj.t = new Date().getTime()
var res = []
// { 'user_name': 'hello', 'user_password': 123 }
for(var key in obj){
res.push(key+'='+obj[key]) //[user_name=hello, user_password=123]
}
// join()方法把数组转换为字符串,用&符号隔开
return res.join('&') //user_name=hello&user_password=123
}
function my_ajax(url,obj,success,error){
// 将传过来的obj对象转换为字符串
var str = obj_str(obj)
var xhr
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest()
}
else {// code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
// var timer = new Date().getTime()
// xhr.open('GET', `${url}&&t=${timer}`, true)
xhr.open('GET', `${url}?${str}`, true)
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
success(xhr)
} else {
error(xhr)
}
}
}
}
调用页面
<script src="./js/my_ajax.js"></script>
<script>
document.getElementsByClassName('btn1')[0].onclick = function () {
my_ajax('http://127.0.0.1:3030', { 'user_name': 'hello', 'user_password': 123 }, function (xhr) {
console.log(xhr.responseText);
}, function (xhr) {
console.log('请求失败');
})
}
</script>
优化:还需要去添加一个请求等待时间的功能,利用我们自己封装的ajax方法请求时,设置一个等待时间,如果在这个时间内没有响应我们的请求,那么我们就自己中断这次请求
在调用my_ajax()方法时传入一个时间参数,如3000毫秒
//调用页面
my_ajax('http://127.0.0.1:3030', { 'user_name': 'hello', 'user_password': 123 }, 3000, seccess(),error()
然后在my_ajax()中用行参timeout接收
//my_ajax.js页面
function my_ajax(url,obj,timeout,success,error){
......
//判断外界是否传入了超时时间
if(timeout){
timer = setInterval(function () {
// abort()方法用于中断请求
console.log('中断请求');
xhr.abort()
clearInterval(timer)
},timeout)
}
}
4. 细节处理
4.1 超时问题
再严谨一点其实当我们判断请求如果完成了就应该把定时器清除掉,因为已经得到了服务器响应,如果此时因为超时而终止请求则中断请求就没有意义了
if (xhr.readyState === 4){
clearInterval(timer)
......
}
4.2 url中文问题
在发送请求的过程中,URL中是不能出现中文的,在obj_str()函数中用encodeURIComponent()方法做处理
URL可以出现:字母/数字/下划线/ASCII码
res.push(encodeURIComponent(key)+'='+encodeURIComponent(obj[key]))
- 封装
3.封装AJAX的POST请求
POST请求的五步操作,基本和GET请求一致
<script>
document.getElementsByClassName('btn1')[0].onclick = function () {
var xhr
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest()
}
else {// code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
console.log(xhr);
xhr.open('POST', 'http://127.0.0.1:3030', true) //方法改为POST
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
console.log(xhr.response)
} else {
console.log('没有接收到服务器的数据')
}
}
}
}
</script>
3.1.POST请求如何传参
GET请求的参数放在URL里面,POST请求的参数放在请求头中
如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:
xhr.open('POST', 'http://127.0.0.1:3030', true)
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send('user_name=bill&user_password=123');
3.2.封装POST请求
和GET请求基本一致,我们直接在封装好的GET请求里面做修改
2.1添加传过来的请求方式参数
2.2对传过来的type值做判断,如果是GET请求则用GET,POST请求则用POST请求方法
function my_ajax(type,url,obj,timeout,success,error){
......
if(type === 'GET'){
xhr.open(type, `${url}?${str}`, true)
xhr.send();
}else{
xhr.open(type, url, true)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(str);
}
......
}
4. jQuery中的ajax
Jq很好的封装了原生的ajax,我们不需要直接创建xmlhttprequest
$.get(url, data, fn, dataType)
$.post(url, data, fn, dataType)
$.ajax()
4.1语法
$.ajax({
name:value,
name:value,
...
})
2.1、语法:
$.ajax({
name:value,
name:value,
...
})
配置项名称 | 描述 |
---|---|
beforeSend(xhr) | 发送请求前运行的函数。 |
async | 布尔值,表示请求是否异步处理。默认是 true。 |
cache | 布尔值,表示浏览器是否缓存被请求页面。默认是 true。 |
contentType | 发送数据到服务器时所使用的内容类型。默认是:“application/x-www-form-urlencoded”。 |
data | 规定要发送到服务器的数据。 |
dataType | 预期的服务器响应的数据类型。它可以指定为html json jsonp script text |
dataFilter(data,type) | 用于处理 XMLHttpRequest 原始响应数据的函数。 |
error(xhr,status,error) | 如果请求失败要运行的函数。 |
success(result,status,xhr) | 当请求成功时运行的函数。 |
timeout | 设置本地的请求超时时间(以毫秒计)。 |
type | 规定请求的类型(GET 或 POST)。 |
url | 规定发送请求的 URL。默认是当前页面。 |
实例
$('.btn3').click(function () {
console.log('ajax');
$.ajax({
// url 给谁发请求
url: 'http://127.0.0.1:3030',
// 发送参数
data: { user_name: 100, user_password: 200 },
// 请求类型
type: 'GET',
//响应体结果
dataType: 'json',
// 请求成功的回调
success: function (res) {
console.log(res);
},
// 超时时间
timeout: 2000,
error: function () {
console.log('出错了');
},
headers: {
a: 80,
b: 90
},
})
})