AJAX

一、简介

1.1 AJAX简介

  • AJAX全称为Asynchronous Javascript And XML,即异步JS和XML
  • 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
  • AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

1.2 XML简介

  • XML:可扩展标记语言
  • XML:被设计用来传输和存储数据
  • XML和HTML类似,不同点:HTML中都是预定义标签,XML中没有预定义标签,全是自定义标签,用来表示一些数据
  • 现在已被JSON取代

1.3 AJAX的特点

1.3.1 AJAX的优点

  1. 可以无刷新页面与服务端进行通信
  2. 允许你根据用户事件来更新部分页面内容

1.3.2 AJAX 的缺点

  1. 没有浏览历史,不能回退
  2. 存在跨域问题(同源)
  3. SEO不友好(爬虫获取不到信息)

1.4 HTTP

HTTP(hypertext transport protocol)协议【超文本传输协议】,协议详细规定了浏览器和万维网服务器之间互相通信的规则

1.4.1 请求报文

重点是格式与参数

行  请求类型:GET/POST     路径URL  /s?ie=utf-8   协议版本HTTP/1.1
头  HOST: blog.sliber.cn
    Cookie: name=LMK
    Content-type: application/x-www-form-urlencoded
    Uer-Agent: chrom 83    
空行
体  username=admin&password=admin

1.4.2 相应报文

行	协议版本:HTTP/1.1    响应状态码200   响应字符串OK
头	Content-Type: text/html;charset=utf-8
	Content-length: 2048
	Content-encoding: gzip

空行
体    <html>
		<head>
		</head>
		<body>
			<h1>ajax学习</h1>
		</body>
	  </html>
	  
响应状态码
404	找不到
403	无权限
401	未授权
500 内部错误
200 ok

二、原生Ajax 及其使用

核心对象:XMLHttpRequest,AJAX的所有操作都是通过该对象进行的。

2.1 基本步骤

  1. 创建XMLHttpRequest对象
    varxhr=newXMLHttpRequest();

  2. 设置请求信息
    xhr.open(method,url);

  3. // 可以设置请求头,一般不设置
    // xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    AJAX请求需要设置withCredentials属性为true,以便允许跨域设置cookie。默认情况下,AJAX请求是不会发送cookie的。在发送AJAX请求前,设置xhr.withCredentials = true,让浏览器发送cookie。注意,服务器也需要在响应头中设置Access-Control-Allow-Credentials: true,允许跨域请求携带cookie。
    xhr.withCredentials = true
    为true就是使用本页面的cookie
    // xhr.setRequestHeader('Cookie', document.cookie)

  4. 发送请求
    xhr.send(body)
    xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
    // get请求不传body参数,只有post请求使用

  5. 接收响应

  xhr.onreadystatechange = function () {
    //判断 (服务端返回了所有的结果)
    if (xhr.readyState === 4) {
      //判断响应状态码 200  404  403 401 500
      // 2xx 成功
      if (xhr.status >= 200 && xhr.status < 300) {
        //处理结果  行 头 空行 体
        //响应 
        console.log(xhr.status);//状态码
        console.log(xhr.statusText);//状态字符串
        // console.log(xhr.getAllResponseHeaders());//所有响应头
        // console.log(xhr.response);//响应体
        // result.innerHTML = xhr.response;
        console.log('xhr.response', xhr.response)
      } else {

      }
    }
  }
  1. 其他函数

    • 设置响应体数据的类型,后面可以自动转换
      xhr.responseType = "json";
    • 超时设置
      xhr.timeout = 2000;
    • 超时回调
      xhr.ontimeout = function(){}
    • 网络异常回调
      xhr.onerror = function(){}
    • 手动取消请求
      xhr.abort();

2.2 AJAX请求状态

xhr.readyState 可以用来查看请求当前的状态

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState

  • 0 (UNSENT)
    表示XMLHttpRequest实例已经生成,但是open()方法还没有被调用。
  • 1 (OPENED)
    表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息
  • 2 (HEADERS_RECEIVED)
    表示send()方法已经执行,并且头信息和状态码已经收到。
  • 3 (LOADING)
    下载中;表示正在接收服务器传来的body部分的数据,responseText 属性已经包含部分数据。
  • 4 (DONE)
    表示服务器数据已经完全接收,或者本次接收已经失败了

2.3 解决IE缓存问题

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

解决方式:浏览器的缓存是根据url地址来记录的,所以我们只需要修改url地址即可避免缓存问题

xhr.open("get","/testAJAX?t="+Date.now())

2.4 实例代码

默认是异步的

// 提前声明,为了可以在其他作用域可以使用xhr.abort()
let xhr = null;
//标识变量
let isSending = false; // 是否正在发送AJAX请求

btn.addEventListener("click", function(){
    //判断标识变量
    if (isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求
    
    //1. 创建对象
    xhr = new XMLHttpRequest();

    //修改 标识变量的值
    isSending = true;
    // 设置响应体数据的类型,后面可以自动转换
    xhr.responseType = "json";
    /*
      // 超时设置 2s
      xhr.timeout = 2000;
      // 超时回调
      xhr.ontimeout = function(){
        alert("网络异常,请稍后重试!");
      }
      // 网络异常回调
      xhr.onerror = function(){
        alert("您的网络似乎出了一些问题!");
      }
    */
    
    //2. 初始化 设置请求方法和 url
    xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
    //3. 发送
    xhr.send();
    //4. 事件绑定 处理服务端返回的结果
    // readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
    // change  改变
    xhr.onreadystatechange = function(){
        //判断 (服务端返回了所有的结果)
        if(xhr.readyState === 4){
            //判断响应状态码 200  404  403 401 500
            // 2xx 成功
            
            //修改标识变量
            isSending = false;

            if(xhr.status >= 200 && xhr.status < 300){
                //处理结果  行 头 空行 体
                //响应 
                // console.log(xhr.status);//状态码
                // console.log(xhr.statusText);//状态字符串
                // console.log(xhr.getAllResponseHeaders());//所有响应头
                // console.log(xhr.response);//响应体
                //设置 result 的文本
                result.innerHTML = xhr.response;
            }else{

            }
        }
    }
});

同步

  const xhr = new XMLHttpRequest()

  // 同步请求不得设置 responseType和timeout

  xhr.ontimeout = function () {
    alert("网络异常,请稍后重试!")
  }
  // 网络异常回调
  xhr.onerror = function () {
    alert("您的网络似乎出了一些问题!")
  }

  // xhrReq.open(method, url, async) 第三个参数就是 是否是异步
  xhr.open('post', 'https://sss.com?w_rid=6a507e3644f11685828e203925c28224&wts=1709401068', false)
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
  xhr.withCredentials = true // 设置为本页面的请求cookie

  // 发送请求
  xhr.send(`msg[sender_uid]=292297687&msg[receiver_id]=647193094`)

  // 同步请求的响应
  if (xhr.readyState === 4) {
    if (xhr.status >= 200 && xhr.status < 300) {
      const res = xhr.response && JSON.parse(xhr.response)
      // console.log('xhr.response', res)
      return res
    } else {
    }
  }

三、jQuery中的AJAX

3.1 GET、POST 请求

$.get(url, [data], [callback], [dataType]);

$.post(url, [data], [callback], [dataType]);

  • url
    请求的URL地址
  • data
    请求携带的参数
  • callback
    载入成功时回调函数
  • dataType
    设置返回内容格式,xml、html、script、json、text、_default

3.2 $.ajax 通用请求

$.ajax({url:"", type:"", [data:{}], [dataType:""], [time:], [success:function], [error:function], [headers:{}]});

  • url
    请求的URL地址

  • type
    GET 或者 POST

  • data
    请求携带的参数

  • dataType
    设置返回内容格式,xml、html、script、json、text、_default

  • time
    超时时间,单位 毫秒

  • success

    成功的回调

  • error
    失败的回调

  • headers
    头信息

3.3 代码示例

// $.get();
$("button").eq(0).click(function () {
    $.get("http://127.0.0.1:8000/jquery-server",
          { a: 100, b: 200 },
          function (data) {
        console.log(data);
    },
          "json");
});

// $.post();
$("button").eq(1).click(function () {
    $.post("http://127.0.0.1:8000/jquery-server",
           { a: 100, b: 200 },
           function (data) {
        console.log(data);
    });
});

// $.ajax
$("button").eq(2).click(function () {
    $.ajax({
        // url
        url: "http://127.0.0.1:8000/jquery-server",
        // 参数
        data: { a: 100, b: 200 },
        // 请求类型
        type: "GET",
        // 响应体结果
        dataType: "json",
        // 成功的回调
        success: function (data) {
            console.log(data);
        },
        // 超时时间
        timeout: 2000,
        // 失败的回调
        error: function () {
            console.log("出错啦!");
        },
        // 头信息
        headers: {
            c: 300,
            d: 400
        }
    });
});

四、axios-AJAX

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 Node.js 中。
也是当下前端非常火热的AJAX工具库。

https://github.com/axios/axios

同jQuery使用AJAX类似

先引入
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>

axios.get(url, {params:{}, headers:{}}).then(value=>{});

axios.post(url, {//请求体}, {params:{}, headers:{}}).then(value=>{});

axios({method:"", url:"", params:{}, headers:{}, data:{}}).then(response=>{});

axios.defaults.baseURL = "http://127.0.0.1:8000"

btns[0].onclick = function () {
    // GET 请求
    axios.get("/axios-server", {
        // url 参数、请求行
        params: {
            id: 100,
            vip: 6
        },
        // 请求头 
        headers: {
            name: "Liwker",
            age: 21
        }
    }).then(value => {
        // promise 的回调
        console.log(value);
    });
}

// POST 请求
btns[1].onclick = function () {
    axios.post("/axios-server", {
        // 请求体
        username: "admin",
        password: "admin"
    }, {
        // 其他配置
        // url参数
        params: {
            id: 200,
            vip: 9
        },
        // 请求头
        headers: {
            height: 180,
            weight: 180
        },
    });
}

// 通用方式
btns[2].onclick = function () {
    axios({
        // 默认是GET方式
        method: "post",
        // url
        url: "/axios-server",
        // url参数
        params: {
            vip: 10,
            level: 30
        },
        // 头信息
        headers: {
            a: 100,
            b: 200
        },
        // 请求体参数
        data: {
            username: "admin",
            password: "admin"
        }
    }).then(response => {
        console.log(response);
        // 响应状态码
        console.log(response.status);
        // 响应状态字符串
        console.log(response.statusText);
        // 响应头信息
        console.log(response.headers);
        // 响应体
        console.log(response.data);
    });
}

五、fetch-AJAX

文档地址(https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch

fetch() 也可以发起AJAX请求,和axios类似

fetcsh(url?参数, {method:"", headers:{}, body:""}).then(response=>{});

btn.onclick = function () {
    fetch("http://127.0.0.1:8000/fetch-server?vip=10", {
        // 请求方法
        method: "post",
        // 请求头
        headers: {
            name: "Liwker"
        },
        // 请求体
        body: "username=admin&password=admin"
    }).then(response => {
        // console.log(response);
        // return response.text();
        return response.json();
    }).then(response => {
        console.log(response);
    });
}

六、跨域

6.1 同源策略

同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。

同源:协议、域名、端口号 必须完全相同。
违背同源策略就是跨域。

6.2 如何解决跨域

6.2.1 JSONP

  1. JSONP是什么

    JSONP (JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求

  2. JSONP 怎么工作的?

    在网页有一些标签天生具有跨域能力,比如:img, link, iframe, script

    JSONP就是利用script标签的跨域能力来发送请求的

  3. JSONP的使用

// 创建handle函数
function handle(data) {
    input.style.border = "1px solid red";
    p.innerHTML = data.msg;
}

input.onblur = function () {
    let username = this.value;

    let scr = document.createElement("script");
    scr.setAttribute("src", "http://127.0.0.1:8000/check-username");
    document.body.appendChild(scr);
}
  1. jQuery中的JSONP
$('button').eq(0).click(function(){
    $.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data){
        $('#result').html(`
        名称: ${data.name}<br>
        校区: ${data.city}
		`)
    });
});

jQuery 的 getJSON, 省去了 JSONP 中的 handle 函数定义

6.2.2 CORS

推荐阅读:

  1. CORS是什么?

    CORS (Cross-Origin Resource Sharing), 跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 等请求。跨域资源共享标准新增了一组 HTTP 首部字段(响应头),允许服务器声明哪些源站通过浏览器有权限访问哪些资源

  2. CORS怎么工作的?

    CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

  3. CORS的使用

    主要是服务端的设置:

app.all("/cors-server", (request, response)=> {
  // 设置响应头,设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  response.setHeader("Access-Control-Allow-Method", "*");

  response.send("Hello CORS!");
});
posted @ 2021-04-21 20:25  Liwker  阅读(61)  评论(0编辑  收藏  举报