原生ajax

  1. 优点
    1. 页面无需刷新与服务器进行通讯获取数据
  2. 缺点
    1. 没有浏览历史,不能回退
    2. 存在跨域问题
    3. SEO不友好,不能进行SEO优化

基本实现

  1. 创建xhr实例
    • const xhr = new XMLHttpRequest()
  2. 配置发送请求方式、url
    • xhr.open('get','http://127.0.0.1:8080/xxx')
  3. 发送请求
    • xhr.send()

请求传参

ajax 有两种请求方式,get/post ,不同请求方式发送的参数格式也不同


GET

  1. query 参数
    • 参数以 urlencoded 编码格式进行声明
    • ?name=老刘&age=18
    • xhr.open('get','http://127.0.0.1:8080/xxx?name=老刘&age=18')
  2. params 参数
    • 参数以 路由 方式进行声明,服务端使用规则进行解析数据
    • /老刘/18
    • xhr.open('get','http://127.0.0.1:8080/xxx/老刘/18')

POST

  1. query 参数
    • 参数以 urlencoded 编码格式进行声明
    • ?name=老刘&age=18
    • xhr.open('post','http://127.0.0.1:8080/xxx?name=老刘&age=18')
  2. params 参数
    • 参数以 路由 方式进行声明,服务端使用规则进行解析数据
    • /老刘/18
    • xhr.open('post','http://127.0.0.1:8080/xxx/老刘/18')
  3. body 参数(请求体参数)
    1. 发送的参数需要传入在 xhr.send()
    2. 有两种编码形式 urlencodedjson
      • urlencoded 格式
        • xhr.send('name=老刘&age=18')
      • json 格式
        • var person = {name:'老刘', age:18}
        • xhr.send(JSON.stringify(person))
    3. 需要 配置 请求体参数编码形式的 请求头
      • 需要在 open之后 send之前,或者 readyState 状态为 1 时,进行配置
      1. urlencoded 格式
        • xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
      2. json 格式
        • xhr.setRequestHeader('Content-type', 'application/json')

获取数据

获取一切数据,都需要在 onreadystatechange属性 定义的函数中进行获取


获取请求状态

  1. xhr实例onreadystatechange属性 赋值函数
    • 当前状态发生改变时会触发此函数
    • on:当xxx时候
    • ready:准备
    • state:状态
    • change:改变
  2. 函数体中通过 xhr.readyState 属性获取改变后的状态(1,2,3,4)
  3. 应该在 new xhr之后open之前 定义 ,如果在open之后定义,将获取不到状态1改变

获取http状态

  1. xhr实例onreadystatechange属性 赋值函数
  2. 函数体调用 xhr.status

获取数据

  1. xhr实例onreadystatechange属性 赋值函数
  2. readyState 配合使用, 一般在状态为4时,调用 xhr.response
1
2
3
4
5
6
7
8
9
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status == 200){
console.log('数据接收完毕:'+ xhr.response) // 获取相应数据
}
}

xhr.open("get","http://localhost:8080") // open之后获取状态

xhr.send() // send之前获取状态

设置获取数据类型

  1. 用于指定返回数据的格式
  2. 在 open 和 send 之间定义
  3. 直接返回 json 对象而不是字符串(将对返回的 json 字符串自动转为 json 对象)
1
2
3
4
5
6
xhr.open("get","http://localhost:8080")

xhr.responseType = "json"

xhr.send()


5种状态

  1. 状态:0
    • 实例出来的那一刻状态就是0。初始状态
  2. 状态:1
    • open已经调用了,但是send还没有调用
    • 此时可以修改请求头内容
  3. 状态:2
    • send已经调用了,已经无法改变请求头
  4. 状态:3
    • 接收到所有响应头
    • 并接收一部分数据,较大数据有待进一步接收
  5. 状态:4
    • 数据全部接收完毕
    • 即使 http 状态码为 404,ajax 依旧接收到了报错数据,所以请求状态会达到 4

异常处理


IE浏览器 get 缓存问题

问题原因

  1. IE 浏览器
    • 相同 get 请求地址,IE浏览器会监测之前是否进行请求过,如果请求过直接使用之前缓存中的数据
  2. 谷歌浏览器
    • 谷歌浏览器的开发者平台,可以通过设置走缓存,如果之前通过 get 请求过相同地址,再次请求时会与 服务器进行协商 ,如果服务端数据没有发生改变返回状态为 304,否则返回最新数据并且状态为 200,谷歌这种使用缓存的机制叫 协商缓存 304

解决 IE 不会与服务器进行协商,直接使用缓存

在 get 请求地址后面传一个时间戳参数,每次 get 地址不同就会重新向服务器发送请求

1
2
3
var xhr = new XMLHttpRequest();
xhr.open("get", "http://xxx/xx/xx?t="+new Date())
xhr.send()

请求报错

给 xhr 的 onerror 属性定义函数,当请求报错时调用此函数

1
2
3
4
5
xhr.open(...)
xhr.onerror = function(){
console.log("请求出错")
}
xhr.send()

请求超时

  1. xhr 属性 timeout 定义等待时间,超时则取消请求
  2. xhr 属性 ontimeout 定义超时处理函数
1
2
3
4
5
6
xhr.open(...)
xhr.timeout = 2000 //等待2秒
xhr.ontimeout = function(){
console.log("请求超时")
}
xhr.send()

取消请求

  1. xhr 调用 abort() 方法,可以取消当前请求
  2. 如果请求已经返回,调用 abort() 没有任何效果
  3. 如果调用了 send() 之后,紧接着调用 abort(),就算请求数据返回也会被拒绝
1
xhr.abort()

避免多次重复请求

  1. 点击发送请求时,事件处理函数中生成新的 xhr 对象,在全局作用域保存
  2. 全局作用域定义是否发送请求状态变量
  3. 每次点击时,检测是否发送了请求,如果发送则调用 abort() 函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var xhr;
var state;

bnt.onclick = function(){
//检测是否发送过了请求
if(state){
xhr.abort(); //发送过了取消请求
}

xhr = new XMLHttpRequest();
xhr.open("get","http://xx/xx/xx");
xhr.send();
state = true; //设置状态,发送了请求
}

jQuery中的ajax


完整

get

1
2
3
4
5
6
7
8
9
$.ajax({
url:"http://xxx/xxx/xx", //请求地址
method:"GET", //请求方式(默认GET)
data:{school:"atguigu"}, //携带数据
dataType:"json", //配置响应数据格式
timeout:2000, //指定超时时间(超时回调也是error)
success:function(a,b,c){...}, //成功回调 a:返回值 b:响应状态 c:xhr
error:function(a){...} //失败回调 a:xhr
})

post

1
2
3
4
5
6
7
8
9
$.ajax({
url:"http://xxx/xxx/xx", //请求地址
method:"POST", //请求方式(默认GET)(自动配置请求头)
data:{school:"atguigu"}, //携带数据
dataType:"json", //配置响应数据格式
timeout:2000, //指定超时时间(超时回调也是error)
success:function(a,b,c){...}, //成功回调 a:返回值 b:响应状态 c:xhr
error:function(a){...} //失败回调 a:xhr
})

精简

get

1
2
3
4
5
6
$.get(
"http://xx/xx/xx", //请求地址
{school:"atuigu"}, //携带参数
function(a){...}, //成功回调 a:返回值
"json" //响应数据格式
)

post

1
2
3
4
5
6
$.post(
"http://xx/xx/xx", //请求地址
{school:"atuigu"}, //携带参数
function(a){...}, //成功回调 a:返回值
"json" //响应数据格式
)

跨域


跨域的原因

浏览器为了安全,采用的同源策略


同源策略

  1. 同源策略是由 Netscape 提出的一个安全策略,现在所有支持 Javascript 的浏览器都使用这个策略
  2. web 是构建在同源策略基础上的,浏览器只是针对同源策略的一种实现

所谓同源是指:前页面url和请求url,协议(http/https)、域名(IP)、端口 必须完全相同


同源策略限制

  1. Cookie 不能读取
  2. DOM 无法获取
  3. Ajax 请求不能获取数据(数据发送了也返回了,但是获取不到,浏览器不允许)

解决跨域


jsonp

只能通过 get 请求实现

发送 get 请求的情况

  1. from 表单
  2. xhr
  3. 浏览器地址栏
  4. img 标签
  5. script 标签
  6. link 标签

实现步骤

  1. 前端定义函数 demo
  2. 服务端返回的字符串,为 demo 调用的字符串 "demo({name:'小明', age:12})",参数为前端需要的数据
  3. 创建 script 标签节点
  4. 定义 script 标签 src 属性为请求的跨域地址
  5. 将 script 节点插入页面
    • 当 script 节点插入页面,服务端返回的函数调用字符串自动执行,demo 函数中即可获取到数据

jquery 实现 jsonp

1
2
3
4
5
6
7
8
9
$.getJSON("http://xxxx/xxx/xxx?callback=?",{...},function(data){...})

// callback=?
// callback:传递自定义函数的属性名,服务端用来接收
// ? :jquery 定义的函数名

// {...} :传递数据

// function(){...} :预定以的函数,传递给服务器的函数的名子

cors

服务器给响应添加一组特殊响应头,允许浏览器接收数据

  1. Access-Control-Allow-Origin
  2. Access-Control-Expose-Headers
  3. Access-Control-Allow-Methods

HTTP 请求有4种

  1. get
  2. post
  3. put
  4. delete

服务端配置方式

  1. put、delete 请求在发送前,会进行以一次预请求(嗅探请求),必须在服务端添加一个 options 响应处理
  2. node.js 服务端,有个 cors 包,可以一次性配置所有响应处理

代理服务器

服务器给服务器发送请求,不受同源策略限制

  1. 数据发送给代理服务器
  2. 通过代理服务器给目标服务器发送请求
  3. 代理服务器接收到数据
  4. 再转发给客户端