学习Ajax的第一天

一、介绍

1.1什么是ajax

网页不刷新的情况下,发送http请求并得到响应。允许根据用户事件来更新部分页面内容
缺点:
1.没有浏览历史,不能回退
2.存在跨域问题(同源)
3.SEO不友好(爬虫不友好)

1.2原生ajax

ajax就是异步的js和xml。

1.3xml介绍

xml 可标记语言被设计用来传输和存储数据
xml和html类似,html是预定义标签,xml是自定义标签

1.4http协议

超文本传输协议,协议详细规定了浏览器和万维网服务器之间互相通信的规则。

二、发送ajax请求

2.1express安装和基本使用

安装node.js,在Webstorm中初始化后安装express
注:初始化是把最外层的包用终端打开初始化

npm init --yes

npm i express

*****如果require没有自动补齐

npm install -D tslib @types/node

基本使用
response和response Headers组合成给我们响应的页面

//引入express模块
const express = require('express');
//创建app应用对象
const app = express();
//创建路由规则
//request是请求报文
//response是响应报文
app.get('/',(request,response) => {
    //设置响应
    response.send('hello world');
});
//监听端口启动服务器
app.listen(3000,() => {
    console.log("服务器启动成功")
})

在这里插入图片描述

2.2发送ajax请求的准备

发送ajax的GET请求准备

//引入express模块
const express = require('express');
//创建app应用对象
const app = express();
//创建路由规则
//request是请求报文
//response是响应报文
app.get('/server',(request,response) => {
    //设置响应头   设置允许跨域
    response.setHeader('Access-Control-Allow-Origin','*');
    //设置响应体
    response.send('hello world');
});
//监听端口启动服务器
app.listen(3000,() => {
    console.log("服务器启动成功")
})

2.3发送ajax GET请求

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            width: 300px;
            height: 150px;
            border: 2px solid pink;
        }
    </style>
</head>
<body>
<button>点击发送请求1</button>
<div id ="div"></div>
</body>
</html>
<script>
    var kk = document.getElementsByTagName('button')[0];
    var div = document.getElementById('div');
    kk.addEventListener('click',function (){
        //创建对象
        const xhr = new XMLHttpRequest();
        //初始化  设置请求方法和url地址
        xhr.open('GET','http://127.0.0.1:3000/server');
        //发送请求
        xhr.send();
        //事件绑定   接受服务器返回的结果
        //on when 当什么时候
        //readstate 是 xhr中的属性  表示状态 0 1 2 3 4
        //change 改变
        xhr.onreadystatechange=function(){
            //判断服务器响应了所有的结果
            if(xhr.readyState === 4){
                //判断服务器响应的状态码  2xx为成功
                if(xhr.status>=200&&xhr.status<300){
                    console.log(xhr.status);  //响应的状态码
                    console.log('------------------------');
                    console.log(xhr.statusText);  //状态字符串
                    console.log('------------------------');
                    console.log(xhr.getAllResponseHeaders());    //所有响应头
                    console.log('------------------------');
                    console.log(xhr.response);   //响应体
                    div.innerHTML=xhr.response;
                }
            }
        }
    })
</script>

如果报错存在跨域问题将设置跨域中的setHeader改为header
emmm 后来发现是Control这个单词写错了

在这里插入图片描述

在这里插入图片描述
设置请求参数
参数是加在url地址后面,用?分割传递多个参数使用&来连接

    xhr.open('GET','http://127.0.0.1:3000/server?a=100&b=200&c=300');

在这里插入图片描述

2.4发送ajax POST请求

将之前的路由请求方式改为post

app.post(‘/server’,(request,response) => {

将open初始化参数改为POST

在这里插入图片描述

设置请求参数是在send发送请求中设置

xhr.send(‘a=100&b=200&c=300’);

在这里插入图片描述

2.5ajax 设置请求头信息

在初始化后发送请求前添加

        //设置请求头   预定义   Content-Type设置请求体内容的类型    后面那一串参数查询字符串的类型
        xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        //设置请求头   自定义  由于浏览器的安全机制需要我们加一个特殊的响应头
        xhr.setRequestHeader('chongqing','gaodenghouwang');

由于浏览器的安全机制需要我们加一个特殊的响应头

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

在这里插入图片描述
此时出现报错 因为浏览器还会发一个OPTIONS的请求来校验检测我们这个头信息可用不可用
因为我们这个请求没有最终的结果 所以我们将创建路由中post改成all

app.all(‘/server’,(request,response) => {
在这里插入图片描述

2.6服务端响应JSON数据

模拟一下后端响应一个对象回去

    //响应一个自定义的数据回去
    const data = {
        "chongqing":"gaodenghouwang"
    }
    //由于我们的send只能返回字符串或者Buffer 咱们做一个转换
    const str = JSON.stringify(data);
    //设置响应体
    response.send(str);

在这里插入图片描述
我们发现数据简单但不美观
咱们前端方面转化一下 手动

					//手动转化JSON为JavaScript对象数据
                    let data = JSON.parse(xhr.response);
                    div.innerHTML=data.chongqing;

需要在初始化前设置响应体数据为JSON 自动

 //设置响应体数据为JSON
        xhr.responseType='json';

两者均可效果一致
在这里插入图片描述

三、ajax关键问题

3.1安装nodemon自动重启工具

解决我们手动重启服务器的东西,让我们更好的偷懒摸鱼,安装nodemon

npm install -g nodemon

如果我们卡在安装窗口一直安装不上,我们配置淘宝镜像

// 配置npm代理来提高速度,设置淘宝镜像
npm config set registry https://registry.npm.taobao.org
// 查看配置是否成功
npm config get registry

再重新安装即可咱们关掉之前的服务 启动nodemon
注:我能们一定是把需要启动的js文件拖拽到终端 并且文件名不能带中文和空格

nodemon AJAX-JSON.js

在这里插入图片描述

3.2ie浏览器的缓存问题

ie存在缓存有可能会出现后端服务器不刷新的情况
我们只需要在请求地址拼接上现在的时间戳即可
在这里插入图片描述

3.3请求超时和网络异常处理

模拟一下后端出错返回了一个空数据,两秒后提示用户。

 let str = '';     //模拟后端出错返回了一个空值
    if(str==''){  //设置两秒的延时给 用户返回出错了
        setTimeout(() => {
            response.send('404找不到网页');
        },2000)
    }else {
        response.send(str);
    }

当然我们也可以在前端设置一秒后没得到返回的数据取消请求

xhr.timeout=1000;

在这里插入图片描述

canceled表示取消的意思,咱们还可以再前端设定请求超时的回调

//请求超时的回调
xhr.ontimeout=function (){
alert(‘请求超时请稍后重试’)
}

如果用户的网络出现异常咱们也可以在前端设置回调

//网络异常的回调
xhr.οnerrοr=function (){
alert(‘你的网络出了问题’)
}

咱们可以借助于chrome浏览器的offline功能模拟一下断网
在这里插入图片描述

3.4手动取消请求

xhr.abort(); //取消请求

<script>
    let xhr = null;
    var btn = document.querySelectorAll('button');
        btn[0].addEventListener('click',function (){
        xhr = new XMLHttpRequest();
        xhr.open('GET','http://127.0.0.1:3000/delay');
        xhr.send();
    })
    btn[1].addEventListener('click',function (){
        xhr.abort();//由于咱们这个局部访问不到xhr所以在外部定义一下
    })
</script>

在这里插入图片描述

3.5面对重复发送请求

为了给我服务器减小压力,用户发送一次请求未成功后再次发送请求会取消上一次请求

<script>
        var btn = document.querySelector('button');
        //获取元素对象
        let xhr = null;
        //检测是否在发送请求
        let isSending = false;
        btn.addEventListener('click',function (){
        //如果正在发送则取消该请求,咱们就可以执行又一次请求
        if (isSending) xhr.abort();
        xhr = new XMLHttpRequest();
        xhr.open('GET','http://127.0.0.1:3000/delay');
        xhr.send();
        isSending = true;
        xhr.onreadystatechange=function (){
            if(xhr.readyState===4){
                //不在状态码判断成功的原因是  请求失败isSending一直处于true
                isSending = false;
            }
        }
    })
</script>

在这里插入图片描述

四、Jquery中发送ajax请求(bootcdn找插件)

后端代码

//引入express模块
const express = require('express');
//创建app应用对象
const app = express();
//创建路由规则
//延时设置
app.all('/axios-server',(request,response) => {
    //设置响应头   设置允许跨域
    response.setHeader('Access-Control-Allow-Origin','*');
    response.setHeader('Access-Control-Allow-Headers','*');
    const data = {chongqing:'gaodenghouwang'};
    response.send(JSON.stringify(data));
});
//监听端口启动服务器
app.listen(3000,() => {
    console.log("服务器启动成功")
})

4.1jquery发送get和post请求

引入Jquery https://www.bootcdn.cn/jquery/

<script>
    $(function (){
        $('button').eq(0).click(function (){
            // url地址   参数   回调函数
           $.get('http://127.0.0.1:3000/jquey-server',{a:100,b:200},function(response){
               console.log(response);
           })
        })
    })
</script>

在这里插入图片描述

发送get要求响应体返回json数据格式 再发送一个post请求

<script>
    $(function (){
        $('button').eq(0).click(function (){
            // url地址   参数   回调函数
           $.get('http://127.0.0.1:3000/jquey-server',{a:100,b:200},function(response){
               console.log(response);
           },'json');   //表示响应体是一个json格式数据
        })
      $('button').eq(1).click(function (){
        // url地址   参数   回调函数
        $.post('http://127.0.0.1:3000/jquey-server',{a:100,b:200},function(response){
          console.log(response);
        });
      })
    })
</script>

在这里插入图片描述

4.2jquery发送ajax请求

如果不使用dataType:‘json’转化为json数据的话接受到的就是一个字符串

<script>
    $(function (){
        $('button').eq(2).click(function (){
           $.ajax({
             //请求的url地址
             url:'http://127.0.0.1:3000/jquery-server',
             //请求参数
             data:{a:100,b:200},
             //请求的响应体返回json数据格式
             dataType:'json',
             //成功时的回调
             success:function (response){
               console.log(response);
             },
             //设置延时返回错误的回调
             timeout:2000,
             error:function (){
               console.log('error');
             }
             //设置头信息
             headers:{
               a:200,
               b:300
             }
           })
        })
    })
</script>

在这里插入图片描述

4.3axios发送get和post请求

发送GET请求
axios的返回结果是基于Promise对象

<script>
          var btn = document.getElementsByTagName('button');
          btn[0].addEventListener('click',function (){
          axios.get('http://127.0.0.1:3000/axios-server',{
            //url  参数
            params:{
              a:100,
              b:200
            },
            //设置请求头
            headers:{
              name:'houwang',
              age:18
            }
          }).then(value => {
            console.log(value)
          })
          })
</script>

data就是响应体自动解析之后的结果
在这里插入图片描述

发送POST请求

btn[1].addEventListener('click',function (){
            //   url   data请求体  ,其他配置
            axios.post('http://127.0.0.1:3000/axios-server',{
              admin:'root',
              password:123456
            },{
              //url  参数
              params:{
                a:100,
                b:200
              },
              //设置请求头
              headers:{
                name:'houwang',
                age:18
              }
            }).then(value => {
              console.log(value)
            })
          })

请求体的话不是发了一个url查询字符串的形式而是一个json格式字符串
在这里插入图片描述

4.4axios发送ajax请求

btn[2].addEventListener('click',function (){
            axios({
              // 请求方法
              methods:'POST',
              //url
              url:'http://127.0.0.1:3000/axios-server',
              //url参数
              params:{
                a:100,
                b:200
              },
              //请求头信息
              headers:{
                name:'houwang',
                age:18
              },
              //请求体参数
              data:{
                admin:'root',
                password:123456
              }
            }).then(response => {
              //响应体状态码
               console.log(response.status);
               //响应字符串
              console.log(response.statusText);
              //响应头
              console.log(response.headers);
              //响应体
              console.log(response.data);
            })
          })

在这里插入图片描述

在这里插入图片描述

4.5使用fetch函数发送ajax请求

fetch函数是属于全局对象的,可以直接调用,返回的结果是一个Promise对象
在这里插入图片描述
很显然这个响应体的结果并不是我们想要的,我们想要的结果可以调用一下这里面的text或者json方法拿到

在这里插入图片描述

<script>
      var btn = document.getElementsByTagName('button');
      btn[0].addEventListener('click',function (){
        //url 请求对象       请求参数直接后缀加
        fetch('http://127.0.0.1:3000/fetch-server?a=100&b=200',{
          //请求方法
          method:'POST',
          //请求头
          headers:{
            name:'houwang'
          },
          //请求体
          body:'username=admin&password=admin'
        }).then(response => {
          // return response.text();  //拿到的一个字符串 我们服务器返回的是一个json
          return response.json();
          //这里如果直接打印会得到一个Promise对象没有值,所以返回出去让下一个then方法来打印
        }).then(response => {
          console.log(response)
        })
      })
</script>

五、跨域问题

5.1同源策略小案例

同源:协议,域名,端口必须完全相同
违背同源策略就是跨域
在这里插入图片描述
注:直接启动这个页面运行是不能获取后端数据的 需要在浏览器输入127.0.0.1:3000/tongyuan

<script>
var btn = document.querySelector('button');
btn.addEventListener('click',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);
            }
        }
    }
})
</script>

在这里插入图片描述

5.2JSONP跨域

JSONP就是借助于script来实现跨域的
这个应该才是src一个完整的书写方式
在这里插入图片描述
咱们这个kuayu.js返回的资源就是Response的内容,再由我们的script标签做一个解析再把这个结果渲染给页面
这就是JSOP的原理
在这里插入图片描述
我堂堂一个script标签给你发请求你给我返回一个这玩意儿,此时控制台是报错的
在这里插入图片描述
js引擎是解析不了的,所以我们一个返回一个js代码
在这里插入图片描述
不难看出后端给我们返回的是一个函数调用
在这里插入图片描述
然后我们的前端正好有这个函数,js就直接解析了所以后端返回的数据直接渲染在页面上
这就是JSONP实现跨域的原理

在这里插入图片描述

5.3JSONP实践

我们做一个用户名输入框,不管输入什么返回咱们都新增一个p标签提示用户名以存在,并且输入框变红

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
用户名:<input type="text">
</div>
</body>
</html>
<script>
    var input = document.getElementsByTagName('input')[0];
    var username = ''
    //onblur事件  当失去焦点时候执行
    input.onblur = function (){
        username = this.value;
       //创建一个script标签
        let script = document.createElement('script');
        //向我们本地的服务器发送请求
        script.src = 'http://127.0.0.1:3000/jsonp';
        //在我们的body下插入这个标签
        //appendChild() 在当前节点的子节点末尾新增一个节点
        document.body.appendChild(script);
    }
    function kk(data){
        var div = document.querySelector('div');
        let p = document.createElement('p');
        div.appendChild(p);
        p.innerHTML=`${username}这个${data.message}`;
        input.style.border='1px solid red';
    }
</script>

可以看出后端给我们返回的是一个函数调用和一个参数
在这里插入图片描述

5.4JQuery发送JSONP请求

做一个按钮,点击按钮发送请求,返回咱们的 框框里面
在这里插入图片描述
虽然我发送请求时callback给的一个?,但在实际发送请求时这个参数是有值的
我们需要把这个callback的值做为函数调用的函数去拼接字符串
也就是说jquery已经是注册了这样的一个函数,只要回来的时候返回的是这个函数 的调用。
咱们的前端就可以对这个代码做一个处理
在这里插入图片描述
此时我们的控制台已经有结果了
在这里插入图片描述
只需要渲染到前端页面即可
在这里插入图片描述

<script>
    $(function (){
        $('button').eq(0).click(function (){
            //必须跟参数callback=?   这是一个固定写法
            $.getJSON('http://127.0.0.1:3000/jquery-JSONP?callback=?',function (data){
                // console.log(data);
                $('div').html(`
                名字:${data.name},
                <br>
                城市:${data.city},
                    `)
            })
        })
    })
</script>

5.5CORS响应头实现跨域

CORS是官方的跨域解决方案,不需要在客户端做任何得到特殊处理操作,完全在服务器中进行处理,支持get和post请求。实现跨域只需要加上一个响应头即可。

response.setHeader('Access-Control-Allow-Origin','*');
<script>
  var btn = document.getElementsByClassName('button');
  btn[0].addEventListener('click',function (){
    //创建对象
    const xhr = new XMLHttpRequest();
    //初始化
    xhr.open('GET','http://127.0.0.1:3000/cors');
    //发送请求
    xhr.send();
    //处理返回结果
    xhr.onreadystatechange = function (){
      if(xhr.readyState === 4){
        if(xhr.status>=200&&xhr.status<300){
          console.log(xhr.response);
        }
      }
    }
  })
</script>

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值