• AJAX(二):axios 和 fetch函数发送AJAX请求、同源策略、 jsonp、CORS


    一、各种发送AJAX请求

    1.axios发送AJAX请求(重点)

    安装axios: 脚手架目录npm i axios
    先配置服务端,类型改成all,然后允许接收自定义请求头啥的

    // (8)axios.html
    app.all('/axios-server', (request, response) => {
        //设置响应头
        response.setHeader('Access-Control-Allow-Origin', '*');// 设置允许跨域
        response.setHeader('Access-Control-Allow-Headers', '*');//接收自定义请求头
        //响应一个数据
        const data = { name: 'ht' };
        let str = JSON.stringify(data); //对对象进行字符串转换
        //设置响应体
        response.send(str);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    axios发送请求成功的值是一个封装好的响应对象:

    在这里插入图片描述
    我们想要的响应数据其实藏在response.data

    来三个按钮:

    <button>GETbutton>
    <button>POSTbutton>
    <button>AJAXbutton>
    
    • 1
    • 2
    • 3
    const get = document.querySelectorAll('button')[0];
    const post = document.querySelectorAll('button')[1];
    const ajax = document.querySelectorAll('button')[2];
    
    • 1
    • 2
    • 3

    (1)GET请求

    get.onclick = function() {
        //GET请求
        axios.get('http://127.0.0.1:8000/axios-server',{
            //url参数
            params: {a:1,b:2},
            //请求头信息
            headers: {name:'zzy',age:18},
            //......
        }).then((response) => {
            //请求成功的回调
            console.log('全部响应结果:',response);
            console.log('响应状态码:', response.status);
            console.log('响应状态字符串:',response.statusText);
            console.log('响应头信息:', response.headers);
            console.log('响应体:', response.data);
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    (2)POST请求

    第二个参数对象里写请求体,第三个参数对象里写url参数和其他信息

       post.addEventListener('click', function() {
            //POST请求
            axios.post('http://127.0.0.1:8000/axios-server',{
                //第二个参数对象里写请求体
                username: 'zzy',
                password: '123'
            },{
                //url参数
                params: {a:1,b:2},
                //请求头信息
                headers: {name:'zzy',age:18}
            })
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (3)axios函数发送通用请求

        ajax.onclick = function() {
        // 通用请求
        axios({
            //请求方法
            method: 'POST',
            //url
            url: 'http://127.0.0.1:8000/axios-server',
            //url参数,传的是query类型参数,只是名字叫params
            params: {a:1,b:2},
            //请求头信息
            headers: {name:'zzy',age:18},
            //请求体参数
            data :{
                username: 'zzy',
                password: '123'
            },
            //超时时间2秒
            timeout:2000
        }).then((response) =>{
            console.log('全部响应结果:',response);
            console.log('响应状态码:', response.status);
            console.log('响应状态字符串:',response.statusText);
            console.log('响应头信息:', response.headers);
            console.log('响应体:', response.data);
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.fetch发送AJAX请求

    fetch比较牛逼的地方在于,它不想jquery和axios需要引入第三方库,它直接就能用,它就在window的内置对象中,直接就能用调用fetch函数。
    fetch当然也有缺点,那就是返回的数据需要包两层promise,还有就是IE不兼容fetch

    服务端随便搞一个

    app.all('/fetch-server', (request, response) => {
        //设置响应头
        response.setHeader('Access-Control-Allow-Origin', '*');// 设置允许跨域
        response.setHeader('Access-Control-Allow-Headers', '*');//接收自定义请求头
        //响应一个数据
        const data = { name: 'ht' };
        let str = JSON.stringify(data); //对对象进行字符串转换
        //设置响应体
        response.send(str);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这里参数在url那传,和axios不太一样,然后响应体拿到的的json字符串,需要转换一下。这里不太熟悉,回头好好看看promise

    btn.onclick = function() {
        fetch('http://127.0.0.1:8000/fetch-server?a=1&b=2',{
            //请求方法
            method: 'POST',
            //请求头
            headers: {name: 'zzy'},
            //请求体
            body: {
                username: 'zzy',
                password: '123'
            }
        }).then((response) => {
            return response.json();  //把json字符串转换为js对象
        }).then(response => { //第二个then处理上一个返回的正确结果
            console.log(response);
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.JQuery发送AJAX请求

    //GET请求
        $('button').eq(0).click(function () {
            $.get('http://127.0.0.1:8000/jquery-server',{
                a:100,b:1000
            },function (data) {//响应体
                console.log(data);
            },'json')//返回JSON类型
        })
        //POST请求
        $('button').eq(1).click(function () {
            $.post('http://127.0.0.1:8000/jquery-server',{
                a:100,b:1000
            },function (data) {//响应体
                console.log(data);
            })
        })
        //通用型方法ajax
        $('button').eq(2).click(function () {
            $.ajax({
               //请求类型
               type:'GET',
               //url
               url: 'http://127.0.0.1:8000/jquery-server',
                //参数
                data:{a:100,b:200},
                //响应体结果设置
                dataType:'json',
                //成功的回调
                success:function (data) {
                    console.log(data);
                },
                //超时时间
                timeout:2000,
                //失败的回调
                error:function () {
                    console.log('出错了!');
                },
                //头信息设置
                headers:{
                   name:"lw",
                    password:"lww"
                }
            });
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    二、同源策略

    同源策略就是协议、域名、端口号必须完全相同,有一个不一样就是跨域
    这个地方听的比较懵,简单记录一下吧
    搞个9000端口,从home传入index.html页面

    const express = require('express');
    
    const app = express();
    
    app.get('/home', (request, response) => {
        //从home进来后,响应一个页面,这个页面里搞的东西都是同样的来源?
        response.sendFile(__dirname + '/index.html'); //拼接的是路径,不要加点
    })
    
    app.get('/data', (request, response) => {
        response.send('用户数据');
    })
    
    app.listen(9000, () => {
        console.log('服务已经启动,9000端口监听中...奥里给');
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在index.html中,因为是在home下的,所以直接向/data发送请求是可以拿到响应体的

    btn.onclick = function() {
        const xhr = new XMLHttpRequest();
        //这里因为满足同源策略,所以url可以简写
        xhr.open('GET', '/data');
        xhr.send();
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4) {
                if(xhr.status >= 200 && xhr.status < 300) {
                    console.log(xhr.response);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、jsonp

    理解不到位,暂时理解成响应体传过去原生js代码,可以解决跨域问题(通过script的src属性请求数据),但只能解决GET。而且这个也要和后端去配合,后端的响应体应该写成js代码才行,所以解决跨域问题用jsonp不多。更多情况是用脚手架的配置代理

    1.原生jsonp

    还是先搞个服务端,响应体传过去一个函数的调用

    // (10)jsonp.html 检测用户名是否存在
    app.all('/jsonp-server', (request, response) => {
        //响应一个数据
        const data = { exist: 1, msg: '用户名已存在' };
        let str = JSON.stringify(data); //对对象进行字符串转换
        //设置响应体
        response.send(`handle(${str})`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实现用户名校验(模拟一下请求js代码的过程,并不是真的校验),服务端的响应体是一个函数的调用,那么我们就应该有这个函数,所以首先要声明handle函数,然后创建script标签,利用其src属性请求数据。

    用户名:<input type="text" id="username">
    <p>p>
    <script>
        const input = document.querySelector('input');
        const p = document.querySelector('p');
    
        //声明handle函数
        function handle(data) {
            input.style.border = '1px solid #f00'; 
            p.innerHTML = data.msg;
            p.style.color = 'red';
        }
    
        input.addEventListener('blur', function() {
            let username = this.value;
            //向服务器发送请求,监测用户名是否存在
            //1.创建script标签
            const script = document.createElement('script');
            //2.设置标签的src属性
            script.src = 'http://127.0.0.1:8000/jsonp-server';
            //将script插入到文档中
            document.body.appendChild(script);
        })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.JQuery发送jsonp请求

    这块儿根本没懂是在干啥
    服务端:

    // (11)JQuery-jsonp.html 
    app.all('/jquery-jsonp-server', (request, response) => {
        //响应一个数据
        const data = { name: 'zzy', age: 18 };
        let str = JSON.stringify(data); //对对象进行字符串转换
    
        //接收callback参数
        let callback = request.query.callback;
        //返回结果,这个callback就相当于是个函数名,相当于handle
        response.send(`${callback}(${str})`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    <button>点击发送jsonp请求button>
    <div id="result">div>
    
    <script>
        $('button').eq(0).click(function() { 
            //使用jquery发送jsonp请求时url后面要加参数callback=?,这是一个固定写法
            //Jquery中的getJSON,省去了jsonp中handle函数的定义,靠callback代替
            //这个callback参数传过去,好像可以变成一个函数,奇怪
            $.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?',function(data){
                $('#result').html(`
                    名称:${data.name}
    年龄:
    ${data.age} `
    ) }) })
    script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    四、CORS

    跨域资源共享,全部都是服务端设置的东西

    	//设置响应头  设置允许跨域
        response.setHeader("Access-Control-Allow-Origin","*");
        //任意头部信息
        response.setHeader("Access-Control-Allow-Headers","*");
        //预请求结果缓存
        response.setHeader("Access-Control-Max-Age","delta-seconds");
        //跨域请求时是否携带验证信息
        response.setHeader("Access-Control-Allow-Credentials","true");
        //设置请求允许的方法
        response.setHeader("Access-Control-Allow-Methods","*");
        //暴露头部信息
        response.setHeader("Access-Control-Expose-Headers","*");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    报告解读下载 | 11月《中国数据库行业分析报告》发布,精彩抢先看
    php将单引号和双引号替换为空字符串
    Java项目源码基于JavaWeb实现的停车场车位收费管理系统
    【C++】加了<string.h>还是报“strlen:找不到标识符”的错误
    PLSQL下载并安装
    element-ui踩坑之表格选中toggleRowSelection问题
    Prometheus指标
    css grid实现九宫格布局
    【微软漏洞分析】MS15-010 CNG 安全功能绕过漏洞 - CVE-2015-0010
    2022年杭电多校第四场补题记录
  • 原文地址:https://blog.csdn.net/weixin_42044763/article/details/126554460