不同方法实现AJAX请求

服务端响应JSON数据

创建文件server.js

// 1、引入express
const express = require('express');
// 2、创建应用对象
const app = express();
app.all('/json-server', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // 响应一个数据
    const data = {
        name: 'atguigu'
    };
    // 对对象进行字符串转换
    let str = JSON.stringify(data);
    response.send(str);
});
// 4、监听端口,启动服务
app.listen(8000, () => {
    console.log("服务已经启动,8000端口监听中..");
})

创建html文件 

<style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #909090;
        }
</style>

    <div id="result"></div>
    <script>
        const result = document.getElementById("result");
        window.onkeydown = function () {
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'json';
            xhr.open('GET', 'http://127.0.0.1:8000/json-server');
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        // result.innerHTML = xhr.response;
                        // let data = JSON.parse(xhr.response);
                        // result.innerHTML = data.name;
                        result.innerHTML = xhr.response.name;
                    }
                }
            }
        }
    </script>

此时数据为JS格式字符串,若想修改为对象有两种方法

方法一手动转化:在if条件输出里面修改为(代码注释部分)

let data = JSON.parse(xhr.response);
result.innerHTML =data.name;

方法二自动转化—设置响应体数据类型

xhr.responseType = 'json';//new方法下添加设置
result.innerHTML = xhr.response.name;//输出方式修改

都可以返回结果,注意大小写和拼写可能为undefined

nodemon自动重启工具安装

由于前面的请求发送中,我们每次都要重启服务,或手动终止特别麻烦,所以此处安装自动工具,之后修改js中send内容就会自动保存,免于来回重启server,会对AJAX的请求结果进行缓存,会导致使用本地缓存而非服务器最新数据

操作如下:

1、在vs终端输入 npm install -g nodemon(红色报错可改为nodemon.cdm server.js)

出现found 0 vulnerabilities表示新版node自带,已经下载好了

2、重启服务nodemon server.js即可

提示:后续文章内容中所修改的server.js部分都是直接在方法下添加,即创建对象和启动服务之间

请求超时与网络异常处理

需要大家手动添加#result的css样式,随意即可,只要能显示出内容

<button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementsByTagName('button')[0];
        const result = document.querySelector('#result');
        btn.addEventListener('click', function () {
            const xhr = new XMLHttpRequest();
            // 超时设置,若2000内无结果则取消
            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>

沿用上面的server.js部分,在下方输入

// 延时响应
app.all('/delay', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 1000)
});

前面安装了自动重启下方终端就会自动保存

点击发送请求之后,即会弹出请求超时的异常提示框

其中网络异常部分是不需要大家拔网线滴~只需要在谷歌浏览器这个位置

将节流模式改为离线模式,即为断网状态,点击发送按钮后也会弹出警示框 

AJAX请求的手动取消

<button>点击发送</button>
    <button>点击取消</button>
    <script>
        const btns = document.querySelectorAll('button');
        let x = null;//声明设置在函数外,let生效与当前作用域
        btns[0].onclick = function () {
            x = new XMLHttpRequest();
            x.open('GET', 'http://127.0.0.1:8000/delay');
            x.send();
        }
        //abort方法进行取消请求,其属于AJAX对象
        btns[1].onclick = function () {
            x.abort();
        }
    </script>

server.js部分与前面延迟响应一致无需修改

可以通过点击和取消,查看控制台的输出情况

请求重复发送

问题:当用户重复点击发送请求,创建多个请求致使服务器压力大

方法:对相同请求进行取消,创建一个最新的请求,缓解服务器压力

<button>点击发送</button>
<script>
   const btns = document.querySelectorAll('button');
   let x = null;
   let isSending = false;
   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();
       // 在完成请求之后,即状态为4时
       x.onreadystatechange = function () {
       if (x.readyState === 4) {isSending = false;
       //不加状态码判断,可能请求为失败请求,在成功条件里判断就无法修改变量}}}
</script>

通过不断点击按钮,查看控制台就会发现,服务器始终只有一个数据请求

jQuery发送AJAX请求

首先第一步是jQuery文件引进

浏览器输入:BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

搜索:输入jQuery并点击,找到jquery.min.js后缀,复制script标签粘贴即可

注:在复制的cdn前添加 crossorigin="anonymous" 可防止报文报错

此处我没有使用bootstrap框架,便自己写了一个样

<style>
h2 {width: 1200px;margin-top: 50px;padding-bottom: 10px;
    font-size: 30px;border-bottom: 1px solid gray;}
button {border-radius: 5px;height: 35px;width: 100px;
    background-color: skyblue;float: left;margin-right: 10px;
    color: white;border: none;text-align: center;}
.btn-primary {background-color: #3587cf;}
.btn-danger {background-color: rgb(12, 190, 226);}
</style>
<body>
    <div class="container">
        <h2 class="page-header">jQuery发送AJAX请求</h2>
        <button class="btn btn-primary">GET</button>
        <button class="btn btn-danger">POST</button>
        <button class="btn btn-info">通用型方法</button>
    </div>
</body>

接下来便是JS代码,若是有多个文件夹,注意server.js放在外层并重新启动服务

前两个为之前所学的GET和POST请求方法

$('button').eq(0).click(function(){
$.get('http://localhost:8000/jquery-server', {a:100, b:200}, function(data){console.log(data)}, 'json')})
//表示响应体是一个json格式的数据
$('button').eq(1).click(function(){
$.post('http://localhost:8000/jquery-server', {a:100, b:200}, function(data){console.log(data)})})
$('button').eq(2).click(function(){
   $.ajax({
       url:'http://localhost:8000/jquery-server',
       data:{a:100, b:222},//参数
       type:'GET',//请求类型
       dataType:'json',//响应体结果
       //成功的回调
       success:function(data){console.log(data)},
       timeout:2000,//超时时间
       //失败的回调
       error:function(){console.log('出错了')},
       //头信息设置
       headers:{
           c:300,
           d:400
       }})})

server.js部分

//jQuery服务
app.all('/jquery-server', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    const data = { name: 'chan' };
    // response.send('Hello jQuery AJAX');
    response.send(JSON.stringify(data));
});

其返回结果一个是对象,一个是字符串

Axios发送AJAX请求

与jQuery相同的方式引入CDN,添加 crossorigin="anonymous"

<style>
button {border-radius: 5px;height: 35px;width: 100px;
        background-color: skyblue;float: left;
        margin-right: 10px;color: white;border: none;text-align: center;}
.btn-primary {background-color: #3587cf;}
.btn-danger {background-color: rgb(12, 190, 226);}
</style>

<button class="btn btn-primary">GET</button>
<button class="btn btn-danger">POST</button>
<button class="btn btn-info">AJAX</button>
<script>
    const btns = document.querySelectorAll('button');
    axios.defaults.baseURL = 'http://127.0.0.1:8000';
    btns[0].onclick = function () {
        //GET请求
        axios.get('/axios-server', {
            //url参数
        params: {id: 100,vip: 7},
            //请求头信息
        headers: {name: 'chan',age: 20}
        }).then(value => {console.log(value);});}
    btns[1].onclick = function () {
           //post请求中,第一个参数url,第二个请求体,第三个其余配置
           axios.post('/axios-server', {
               username: 'admin',
               password: 'admin'
           }, {//url参数
               params: {id: 200,vip: 9},
               //请求头参数
               headers: {name: 'chan',age: '20'},
               //请求体
           })}
      // axios函数发送请求
      btns[2].onclick = function () {
          axios({method: 'POST',url: 'axios-server',
              //url参数
              params: {vip: 10,leve: 30},
              //头信息
              headers: {a: 100,b: 200},
              //请求体参数
              data: {name: 'chan',age: '20'}
          }).then(response => {
              console.log(response);
              // 响应状态码
               console.log(response.status);
               //响应状态字符串
               console.log(response.statusText);
               // 响应头信息
               console.log(response.headers);
               // 响应体
               console.log(response.data);
})}</script>

server.js部分 

//axios服务
app.all('/axios-server', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    const data = { name: 'chan' };
    // response.send('Hello jQuery AJAX');
    response.send(JSON.stringify(data));
});

同源策略

AJAX默认遵循策略—即协议、域名、端口号完全相同

违背同源策略也称为跨域,http/https协议、8000/5500端口、a.com/b.com这种两者间的请求,即为跨域

新建一个文件夹,单独的放入index与server,

<h1>chan Hi</h1>
<button>点击获取用户数据</button>
<script>
        const btn = document.querySelector('button');
        btn.onclick = function () {
            const x = new XMLHttpRequest();
            x.open('GET', 'http://127.0.0.1:9000/data');
            x.send();
            x.onreadystatechange = function () {
                if (x.readyState === 4) {
                    if (x.status >= 200 && x.status < 300) {
                        console.log(x.response);
                    }
                }
            }
        }
</script>

过程中,我研究了好久也不明白为什么我的需要设置跨域和完整URL的问题

无论是vs打开还是端口都报错,希望有懂的大佬可以分析一下

新建的server下代码

const express = require('express');

const app = express();

app.get('/home', (request, response) => {
    response.sendFile(__dirname + '/index.html');
});

app.get('/data', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.send('用户数据');
});
app.listen(9000, () => {
    console.log('端口9000服务已经启动');
});

jsonp

此处依然是新建一个jsonp文件夹

这边先看代码,后面原理再进行阐述

<style>
div {width: 100px;height: 100px;border: 1px solid #78a;}</style>
<!-- jsonp不受同源策略限制,通过get方式执行后端返回的js脚本 -->
<div id="res"></div>
<script>
    function handle(data) {
        const res = document.getElementById('res');
        res.innerHTML = data.name;
    }
</script>
<script src="http://127.0.0.1:8000/jsonp-server"></script>

文件夹中额外添加一个app.js

const data = {
    name: 'chan'
};

console.log(data);

handle(data);

但不需要新建js文件,写回之前的server.js中即可 

//jsonp 服务
app.all('/jsonp-server', (requesr, response) => {

    const data = { name: 'chan' }
    //设置响应
    let str = JSON.stringify(data)
    // response.send('console.log("hello jsonp")')
    response.send(`handle(${str})`)
    //此处非引号而是esc下放的反引
})

其个人所理解的原理是:(若有理解错误的地方,欢迎指正)

首先jsonp不受同源策略限制

/jsonp-server返回的是一个函数调用handle(),此处函数的形参就是实参chan

也就是我们想要返回给用户的数据,随后再让前端中提前声明好的函数handle进行处理

jsonp实践

前面原理没有看懂也没有关系,下面的实践内容帮助你进一步理解

如下面的例子,用户输入用户名,由于没有数据库等内容,无论用户输入什么,我们都让其返回‘用户已存在’,这就是我们所想要给用户返回的数据

用户名:<input type="text" id="username">
<p></p>
<script>
    const input = document.getElementById('username')
    const p = document.querySelectorAll('p')[0]
    function handle(data) {
        input.style.border = "solid 1px #f00"
        p.innerHTML = data.msg}//修改p标签的提示文本
    //失去焦点事件
    input.onblur = function () {
        let username = this.value
        //向服务端发送请求;1 设置script标签
        const script = document.createElement('script')
        //2 设置标签的src属性
        script.src = 'http://localhost:8000/check-username'
        //3 将script插入文档中
        document.body.appendChild(script)}
</script>
//用户名检测是否存在
app.all('/check-username', (requesr, response) => {

    const data = {
        exist: 1,
        msg: '用户名已经存在'
    }
    let str = JSON.stringify(data)
    response.send(`handle(${str})`)

})

//用户名检测是否存在
app.all('/jquery-jsonp-server', (request, response) => {

    const data = {
        name: 'chan',
        age: 20
    }
    //设置响应
    let str = JSON.stringify(data)
    //接受callback参数
    let cb = request.query.callback
    response.send(`${cb}(${str})`)

})

此时无论输入什么形式都会显示已存在

如果本文存在内容遗漏、说明不清或是有问题的地方,欢迎大家提出一起解决,也希望本文对大家有所帮助

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值