Ajax:原生+Jquery+Axios+CORS跨域

一、Ajax简介

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

二、学习前的准备

需要对js的基础语法有一定的了解

三、后端的准备工作

这里我们不使用Django这种比较大的框架来实现,我们只用Node.JS,可以下载安装一下这个框架express,再安装一个插件nodemon

在当前目录下执行下面的命令

npm init --yes
npm i express

在当前的目录下创建一个app.js

// 引入express
const express = require('express');
const res = require('express/lib/response');
// 创建应用对象
const app = express();

// 可以接受任意类型的请求,这里也可以设置为post或者get
// 路由卸载第一个参数内
app.all('/server', (request, response) => {
    // 设置响应头可以接受任何的响应头可以接受跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Header', '*');
    // 设置响应体,也就是返回的数据
    response.send('HELLO Ajax');
})

// 可以接受任意类型的请求
app.all('/json', (request, response) => {
    // 设置响应头 设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Header', '*');
    const data = {
        name : 'atguigu',
        age : 18
    };
    // 将对象数据转换为JSON字符串
    let str = JSON.stringify(data)
    // 设置响应体
    response.send(str);
})

app.all('/time', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    const data = {
        name : 'atguigu',
        age : 18
    };
    let str = JSON.stringify(data)
    setTimeout(
        function () { 
            response.send(str)
        },3000)
})	

// 设置监听的端口号
app.listen(8000, () => {
    console.log("服务已经启动,8000端口正在监听中");
})

然后我们启动应用

node app.js

四、原生JS-Ajax

发送get请求
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #result {
        width: 200px;
        height: 100px;
        border: solid 1px #90b;
    }
</style>

<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.querySelector('button');
        // 给按键绑定事件
        btn.onclick = function(){
            // 创建对象
            const xhr = new XMLHttpRequest();
            // 初始化,设置请求方法和URL
            xhr.open('GET','http://127.0.0.1:8000/server');
            // get的参数 ?a=100&b=200&c=300
            // 发送
            xhr.send()
            // 事件绑定,处理服务端返回的结果
            // readystate 是xhr对象中的属性,标示状态0 1 2 3 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);
                        // 2.响应体
                        console.log(xhr.response);
                    }
                }
            }
        }
    </script>
</body>

</html>
发送post请求

发送post请求的方法和get是很相似的,只是xhr的方法改为post

result.addEventListener('click',function(){
    var xhr = new XMLHttpRequest();
    xhr.open('POST','http://127.0.0.1:8000/server');
    // 设置请求头的信息
    xhr.setRequestHeader('Content-type','text/plain')
    xhr.setRequestHeader('name','atue')
    xhr.send();
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
        	if(xhr.status >= 200 && xhr.status<300){
        		result.innerHTML=xhr.response;
			}
		}
	}
})
发送和接收JSON字符串

这里是给/json路由发送的信息,在这里服务端用了一个方法JSON.stringify把对象转换为字符串,客户端用了一个方法JSON.parse将字符串转换为对象

<script>
    const result = document.querySelector('#result')
    window.onkeydown = function(){
        const xhr = new XMLHttpRequest();
        xhr.open('GET','http://127.0.0.1:8000/json');
        xhr.send();
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(xhr.status >= 200 && xhr.status<300){
                    console.log(xhr.response);
                    let data = JSON.parse(xhr.response);
                    result.innerHTML = data.name;
                }
            }
        }
    }
</script>
设置超时时间和网络异常情况

/time 路由设置了定时器,3s后返回,我们在客户端设置2s超时时间,故意创造了一个bug

<script>
    const btn = document.querySelector('button')
    const result = document.querySelector('#result')
    btn.onclick = function(){
        const xhr = new XMLHttpRequest();
        // 超时时间的设置,单位毫秒
        xhr.timeout = 2000;
        // 超时的回调函数
        xhr.ontimeout = function(){
            alert('网络异常,请稍后')
        }
        // 网络异常的回调
        xhr.onerror = function(){
            alert('网络出问题啦')
        }
        xhr.open('GET','http://127.0.0.1:8000/time');
        xhr.send();
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(xhr.status >= 200 && xhr.status<300){
                    console.log(xhr.response);
                    let data = JSON.parse(xhr.response);
                    result.innerHTML = data.name;
                }
            }
        }
    }
</script>
取消发送

取消发送一般是用于重复请求问题,重复的请求过多会对服务器造成压力

<script>
    const btn = document.querySelector('button')
    let isSending = false;
    btn.onclick = function(){
        const x = new XMLHttpRequest();
        if(isSending){
            x.abort // 如果创建一个新的,那也只能最后一个发送
        }
        isSending = true;
        x.open('GET','http://127.0.0.1:8000/time')
        x.send();
        x.onreadystatechange = function(){
            if(x.readyState===4){
                isSending = false;
                if(xhr.status >= 200 && xhr.status<300){
                    console.log(xhr.response);
                    let data = JSON.parse(xhr.response);
                    result.innerHTML = data.name;
                }
            }
        }
    }
</script>
fetch发送
<script>
    const btn = document.querySelector('button')
    btn.onclick = function(){
        fetch('http:127.0.0.1:8000/json',{
            method:'POST',
            headers:{
                id:7,
                vip:8,
            },
            body:JSON.stringify({password:'123'})
        }).then(response=>{
            return response.json()
        }).then(response=>{
            console.log(response)
        })
    }
</script>

五、JQuery-Ajax

JQuery有三种方法发送请求,分别是get方法,post方法和通用方法

<body>
    <h2>jquery发送Ajax请求</h2>
    <button>GET</button>
    <button>POST</button>
    <button>通用型方法</button>
    <script>
        $('button').eq(0).click(function () {
            $.get('http:127.0.0.1:8000/json', { a: 100, b: 200 }, function (data) {
                // data是回调得到的参数
                console.log(data)
            })
        })
        $('button').eq(1).click(function () {
            $.post('http:127.0.0.1:8000/json', { a: 100, b: 200 }, function (data) {
                data = JSON.parse(data);
                console.log(data.name);
            })
        })
        // 通用方法发送请求
        $('button').eq(2).click(function () {
            $.ajax({
                // url
                url: 'http:127.0.0.1:8000/json',
                //参数 
                data: { a: 100, b: 200 },
                //请求类型
                type: 'GET',
                // 成功的回调函数
                success: function (data) {
                    data = JSON.parse(data);
                    console.log(data.name);
                },
                // 失败的回调
                error: function () {
                    console.log('网络异常')
                },
                // 超时时间
                timeout: 3000,
                // 头信息
                headers = {
                    c: 300,
                    d: 400,
                }
            })
        })
    </script>
</body>

六、Axios-Ajax

使用axios需要先引用这个文件

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
<body>
    <button>GET</button>
    <button>POST</button>
    <button>AJAX</button>
    <script>
        const btns = document.querySelectorAll('button');
        // 配置baseURL,这样的话后面的链接就会自动和这个地址拼接
        axios.defaults.baseURL = 'http://127.0.0.1:8000';
        btns[0].onclick = function () {
            axios.get('/json', {
                // URL参数
                params: {ID: 1234,VIP: 7},
                headers: {name: 'LYJ'}
            }).then(value => {
                console.log(value)
            })
        }

        btns[1].onclick = function () {
            axios.post('/json',
            // 表单参数
            {username: 'admin',password: '123'},
            // 其他参数 
            {params: {ID: 1234,VIP: 7},headers: {name: 'LYJ'},}
            ).then(response=>{
                console.log(response.status)
            })
        }

        btns[2].onclick = function () {
            axios({
                method: 'POST',
                url: '/json',
                params: {vip: 2,id: 2},
                headers: {a: 100,b: 200},
                data: {username: 'admin',password: '123'}
            }).then(response => {
                console.log(response);
                console.log(response.status);
                console.log(response.statusText);
                console.log(response.headers);
                console.log(response.data);
            })
        }
    </script>
</body>

七、怎么解决跨域问题

同源策略

如果两个 URL 的 protocolport (en-US) (如果有指定的话)和 host 都相同的话,则这两个 URL 同源

下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

URL结果原因
http://store.company.com/dir2/other.html同源只有路径不同
http://store.company.com/dir/inner/another.html同源只有路径不同
https://store.company.com/secure.html失败协议不同
http://store.company.com:81/dir/etc.html失败端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html失败主机不同

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

解决跨域问题

我们不可能只访问一个服务器的资源,当我们访问不同的服务器资源时,跨域问题必将显现出来

针对跨域问题我们重新写一个服务端,注意我们这个服务端监听9000端口

const { request, response } = require('express');
const express = require('express');

const app = express();

app.get('/home', (request, response) => { 
    // 响应一个页面,即发送index.html
    response.sendFile(__dirname+'/index.html')
})

app.get('/data', (request, response) => {
    response.send('用户数据')
})

app.listen(9000, () => { 
    console.log('服务已经启动')
})

我们写一个get请求,这个页面命名为index.html

<body>
    <button>点击获取服务端数据</button>
    <div>ready</div>
    <script>
        const btn = document.querySelector('button');
        const mydiv = document.querySelector('div');
        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){
                        mydiv.innerHTML=xhr.response;
                    }
                }
            }
        }
    </script>
</body>

此时是可以请求成功的,但是我们向http://127.0.0.1:8000/server这个路由发送请求时,发现出现了跨域问题,由于端口号的不一致,我们无法访问。

此时可以使用jsonp,这个策略是因为一些标签天生具有跨域能力img,vedio,script,iframe等等,这样的话我们可以把数据放入script的js数据中进行访问。

这里我们用jquery

$.getJSON('http://127.0.0.1:8000/server?callback=?',function(data){
	console.log(data)
})

后端需要接受callback字符串

let cb = request.query.callback
response.end('${cb}($(str))')
CORS解决方案

这是一个官方的解决方案,她的特点是不在客户端操作,全部在服务器完成,通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会放行,

在我们的node.js服务其中就是设置这个字段,*统配所有字符,这里我们就可以设置可以放行的域

response.setHeader('Access-Control-Allow-Origin', '*');

例如我们设置为

response.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:9000/server');

这样我们之前写的那个9000端口的服务就可以访问了

更多地CORS文档https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LyaJpunov

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值