简介

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

优点

  • 无需刷新页面即可与服务器进行通信。
  • 允许根据用户事件来更新部分页面内容。

缺点

  • 没有浏览历史,不能回退
  • 存在跨域问题,ajax默认是遵循同源策略,跨域请求是无法通过ajax请求的
  • seo不友好,无法通过爬虫获取到ajax请求的数据,也无法在浏览器的源代码选项中获取到相关的源码

总而言之:ajax不是什么新鲜的对象,我们把它当作是在一个已有的网页中,我们可以通过它请求后端的数据来显示在之前的网页中。

AJAX的使用

  • GET请求
btn.onclick = function(){            //1. 创建对象            const xhr = new XMLHttpRequest();//浏览器开发者选项中的xhr里面的信息就是该页面的ajax请求            //2. 初始化 设置请求方法和 url            xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');            //3. 发送            xhr.send();            //4. 事件绑定 处理服务端返回的结果            xhr.onreadystatechange = function(){                //判断 (服务端返回了所有的结果)                if(xhr.readyState === 4){                    // 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 的文本                        result.innerHTML = xhr.response;                    }else{                    }                }            }        }
  • POST请求
result.addEventListener("mouseover", function(){            //1. 创建对象            const xhr = new XMLHttpRequest();             xhr.responseType='json'            //2. 初始化 设置类型与 URL            xhr.open('POST', 'http://127.0.0.1:8000/server');//有时候ie浏览器会有缓存问题,因此通常情况下最好给每个url拼接上一个时间戳参数            //设置请求头            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');            xhr.setRequestHeader('name','xxx');//自定义的请求头需要在后端中设置Access-Control-Allow-Headers响应头            //3. 发送            xhr.send('a=100&b=200&c=300');            // xhr.send('a:100&b:200&c:300');            // xhr.send('1233211234567');                        //4. 事件绑定            xhr.onreadystatechange = function(){                //判断                if(xhr.readyState === 4){                    if(xhr.status >= 200 && xhr.status < 300){                        //处理服务端返回的结果                        result.innerHTML = xhr.response;                    }                }            }        });
  • 超时与网络异常问题
btn.addEventListener('click', function(){            const xhr = new XMLHttpRequest();            //超时设置 2s 设置            xhr.timeout = 2000;            //超时回调            xhr.ontimeout = function(){                alert("网络异常, 请稍后重试!!");            }            //网络异常回调            xhr.onerror = function(){                alert("你的网络似乎出了一些问题!");            }            xhr.open("GET",'http://127.0.0.1:8000/delay');            xhr.send();            xhr.onreadystatechange = function(){                if(xhr.readyState === 4){                    if(xhr.status >= 200 && xhr.status< 300){                        result.innerHTML = xhr.response;                    }                }            }        })
  • 重复请求问题——关键在于设置一个标志位
    <script>        //获取元素对象        const btns = document.querySelectorAll('button');        let x = null;        //标识变量        let isSending = false; // 是否正在发送AJAX请求        btns[0].onclick = function(){            //判断标识变量            if(isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求            x = new XMLHttpRequest();            //修改 标识变量的值            isSending = true;            x.open("GET",'http://127.0.0.1:8000/delay');            x.send();            x.onreadystatechange = function(){                if(x.readyState === 4){                    //修改标识变量                    isSending = false;                }            }        }        // abort        btns[1].onclick = function(){            x.abort();        }    </script>
  • 使用express框架搭建一个后端
//1. 引入expressconst express = require('express');//2. 创建应用对象const app = express();//3. 创建路由规则// request 是对请求报文的封装// response 是对响应报文的封装//all方法表示所有类型的请求都可以,get、post、delete。。。app.all('/server', (request, response)=>{    //设置响应    //response.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");//只对http://127.0.0.1:3000这个url的请求允许跨域    response.setHeader("Access-Control-Allow-Origin","*")//对所有请求允许跨域    response.setHeader("Access-Control-Allow-Headers","*")//允许各种请求头,包括自定义的和http已经定义的请求头    response.send('HELLO EXPRESS');});//4. 监听端口启动服务app.listen(8000, ()=>{    console.log("服务已经启动, 8000 端口监听中....");});

AJAX的请求状态

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

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

跨域问题

  • 同源策略
    同源策略是浏览器的一种安全策略。所谓的同源是指:协议、域名】端口号必须完全相同,而违背同源策略就是跨域。
    如果违背同源策略,浏览器的开发者工具就会报如下错误,该网页是从5500端口获取的,但是ajax的请求却是8000端口。

    解决跨域问题有两种方式:

  • CORS

    1. CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
    2. CORS 怎么工作的?
      CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
  • JSONP
    JSONP(JSON with Padding),是一个非官方的跨域解决方案,只支持 get 请求。在网页有一些标签天生具有跨域能力,比如:img link iframe script。JSONP 就是利用 script 标签的跨域能力来发送请求的。

    案例如下:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>案例</title></head><body>    用户名: <input type="text" id="username">    <p></p>    <script>        //获取 input 元素        const input = document.querySelector('input');        const p = document.querySelector('p');                //声明 handle 函数        function handle(data){            input.style.border = "solid 1px #f00";            //修改 p 标签的提示文本            console.log(data)            p.innerHTML = data.name;        }        //绑定事件        input.onblur = function(){            //获取用户的输入值            let username = this.value;            //向服务器端发送请求 检测用户名是否存在            //1. 创建 script 标签            const script = document.createElement('script');            //2. 设置标签的 src 属性            script.src = 'http://127.0.0.1:8000/server';            //3. 将 script 插入到文档中            document.body.appendChild(script);        }    </script></body></html>
//1. 引入expressconst express = require('express');//2. 创建应用对象const app = express();//3. 创建路由规则// request 是对请求报文的封装// response 是对响应报文的封装app.all('/server', (request, response)=>{    //设置响应    // response.setHeader("Access-Control-Allow-Origin","*")    // response.setHeader("Access-Control-Allow-Headers","*")    const data = {        name: 'sdsdsd'    };    response.end(`handle(${JSON.stringify(data)})`);//这样就会回调到html中的handle方法});//4. 监听端口启动服务app.listen(8000, ()=>{    console.log("服务已经启动, 8000 端口监听中....");});

最后

除了前面介绍的几个字ajax的请求之外,fetch函数也是可以用来进行ajax请求的
https://developer.mozilla.org/zh-CN/docs/Web/API/fetch