初学Ajax

HTTP

三次握手和四次挥手

初学Ajax_第1张图片
2MSL:两个时间单位,一来一回。两个时间单位里如果收到消息了,说明服务器还没有关,如果两个时间单位里没有收到消息,则说明服务器已经关闭了。

http协议的构成

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

请求

请求行:请求行包括三部分:请求类型,url路径,HTTP协议的版本。请求类型有get、post、delete、put 、push

请求头(request header):请求头名称:请求头内容;即为key:value格式。比如:Host:localhost;Cookie:name = baidu ;Content-type(告知服务器请求是什么类型的):application/x-www-form-urlencode;等

请求体(request body)这次请求的主体信息。如果是get请求,请求体是空的;如果是post请求,请求体可以为空可以不为空。

请求报文:请求行+请求头+空行+请求体

响应

响应行:包括三部分:HTTP协议版本,响应状态码,响应字符串

响应头(response header):格式和请求头格式一样。比如:Content-Type:text/html;charset=utf-8;Content-length:2048;Content-encoding:gzip;
属性一:content-type:内容的类型,后端向前端返回的数据类型

响应体(response body):真正的数据

响应报文:响应行+响应头+空行+响应体

开发者工具

Preview:做一个响应的预览,即响应的解析,对响应体内容解析之后的一个查看
Response:响应体,服务器返回的html内容

Headers

General
Response Headers(响应头):点击view source,得到响应行和响应头,响应体在response中
Request Headers(请求头):点击view source,就会得到请求行
From Data:当请求为post请求时,请求体携带的参数。点击 view source,原始的请求体内容
Query String Parameters(查询字符串参数),是对url中的参数做一个解析

同步异步

js特点

js是单线程的语言,对于拿到的程序,只能一行一行的执行,如果上面的代码未执行,下面的代码就只能等待,这样的代码是同步(sync)的

初学Ajax_第2张图片

一段代码

初学Ajax_第3张图片
结果为10,虽然定时器的时间为0,但是仍然是异步代码。异步代码总是在同步代码之后执行的。

Ajax基础

认识Ajax(Asynchronous JavaScript And XML:异步的js和xml)

Ajax前:用户触发一个http请求服务器,服务器收到后,作出响应到客户,并返回一个新的页面。所以说交互都是通过页面刷新或者页面跳转实现的。但这样的方式并不好,如果只是少量的数据更新,也会引发整个页面重新请求,浪费了很大一部分资源。

XML简介

  • XML可扩展标记语言(跟HTML一样,也是由标签组成的)
  • 被设计用来传输和存储数据(HTML是在网页中呈现数据的)
  • XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全是自定义标签,用来表示一些数据
  • 以前后端向前端返回数据使用的是XML字符串,现在已经变为JSON字符串了,相对于XML,JSON更加简洁。

Ajax作用:

作用:专门用于网页和服务器之间交换数据的.(异步的javaScript和XML),是一种无需重新加载整个网页的情况下,能够更新部分网页的技术.。通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。

服务器:实质就是一台"提供了某种服务功能"的超级电脑

  • 如何让电脑提供管理网站的服务?
    答:安装Web服务相关的软件.例如:Apache,IIS,Tomcat,Nginx,NodeJS等
  • 后端编写的代码不能直接运行,只能放到服务器对应的文件夹下,通过服务器运行
  • 如何通过服务器运行:通过ip地址找到服务器对应的文件夹,然后再找到对应的文件运行

使用Ajax和不使用Ajax的区别:

  • 传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页
  • 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
  • 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。

Ajax的特点

优点:

  1. 不需要插件支持(一般浏览器只要默认开启JavaScript即可)
  2. 用户体验极佳(不刷新页面即可获得可更新的数据)
  3. 提升Web程序的性能(在传递数据方面做到按需发送,不必整体提交,允许根据用户事件来更新部分页面内容)
  4. 减轻服务器和带宽的负担(将服务器的一些操作转移到客户端;在传统的交互中,服务器需要给浏览器返回整个页面,在这个过程中不可避免的服务器会产生很多运算,如果有100个浏览器同时向服务器发送同样的请求,那么服务器就会做100次重复的运算,而现在有了Ajax后,前端给后端发送请求,后端只负责返回数据,真正的运算是分配给这100个浏览器去运算的,因此,对服务器的压力比较小,交互量也比较小)

缺点

  1. 前进,后退功能被破坏(因为Ajax永远在当前页,不会记录前后页面)
  2. 搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解JS引起变化数据的内容,只能抓取服务器本身的数据)
  3. 存在跨域问题(同源)

常见的状态码

  1. 100-199:表示连接继续
  2. 200-299:表示各种意义上的成功
  3. 300-399:表示重定向
  4. 400-499:表示各种客户端错误
  5. 500-599:表示何种服务端错误

利用Ajax可以做什么

  • 注册时,输入用户名自动检测用户是否已经存在。
  • 登陆时,提示用户名密码错误
  • 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除

一个比喻

页面-------------Ajax-------------后台
(顾客----------服务员-----------厨房)
初学Ajax_第4张图片
在后台计算的过程中,前端页面不受任何影响,因为他是一个异步请求,并不会因此而卡顿

发送一个get请求

不携带参数时:

前端代码:

readystate是xhr对象中的属性,表示状态 ,取值为0-4。

  • 0(未初始化)
  • 1(open方法调用完毕)
  • 2(send方法调用完毕)
  • 3(服务端返回了部分结果)
  • 4(服务端返回了所有结果)
<body>
  <button onclick="sendMsg()">发送请求</button>
  <script>
    function sendMsg(){
    //1.创建一个XMLHttpRequest对象
      let xhr = new XMLHttpRequest();
    //2.调用open方法打开连接
    //  open 方法有三个参数:
        //1.请求的method:一般为get,post等
         //2.请求的url地址
        //3.是否异步,默认为true,即默认异步,故而这个参数可以不用传
      xhr.open('get','./data.php');
    //3.发送请求(请求体)
      xhr.send();
    //4.监听状态的改变
      //onreadystatechange这个事件会触发很多次,所以需要判断到底哪一次代表成功
      xhr.onreadystatechange = function (){
        //判断状态值:0-4;4代表最终的完成
        if(xhr.readyState === 4){
        //判断状态码
          if (xhr.status === 200){
            console.log(xhr.responseText);
          }
        }
      }
    }
  </script>
</body>

后端代码


echo ‘hello ajax’;
?>

返回了一个字符串

携带参数时

前端代码

<body>
  <button onclick="sendMsg()">发送请求</button>
  <script>
    function sendMsg(){
    //1.创建一个XMLHttpRequest对象
      let xhr = new XMLHttpRequest();
    //2.调用open方法打开连接
    //  open 方法有三个参数:
        //1.请求的method:一般为get,post等
         //2.请求的url地址
        //3.是否异步,默认为true,即默认异步,故而这个参数可以不用传
      xhr.open('get','./data.php?id=1);
    //3.发送请求
      xhr.send();
    //4.监听状态的改变
      //onreadystatechange这个事件会触发很多次,所以需要判断到底哪一次代表成功
      xhr.onreadystatechange = function (){
        //判断状态值:0-4;4代表最终的完成
        if(xhr.readyState === 4){
        //判断状态码
          if (xhr.status === 200){
            console.log(xhr.responseText);
          }
        }
      }
    }
  </script>
</body>

后端代码


$id = $_GET[‘id’];
echo json_encode(array(
	‘id’ => $id,
	‘title’ => $’hello ajax’
))
?>

此时给前端返回的就是json格式的数据,{‘id’:’1’,’title’:’hello ajax’},实际上是一个字符串,即服务器返回的是一个满足json格式的字符串,因此需要对这个字符串进行解析

if (xhr.status === 200){
	let resp = JSON.parse(xhr.responseText)
   console.log(resp);
}

发送一个post请求

Get和post区别

  1. get的大小是有限制的,因为它的参数放在请求头的,所以大小在4k左右,而post的参数放在请求体中的,所以没有限制
  2. get参数是放在请求头中,而post参数是放在请求体中的
  3. get是明文传输,而post相对来说更安全一些

不携带参数时

前端代码

<body>
  <button onclick="sendMsg()">发送请求</button>
  <script>
    function sendMsg(){
      let xhr = new XMLHttpRequest();
      //这里的方法改为:post
      xhr.open('post','./data.php');
      xhr.send();
      xhr.onreadystatechange = function (){
        if(xhr.readyState === 4){
          if (xhr.status === 200){
            console.log(xhr.responseText);
          }
        }
      }
    }
  </script>
</body>

与get基本相同,只改变了open中的方法参数,由get改为了post

携带参数时

前端代码

初学Ajax_第5张图片
除了open里写post以外,还设置了请求头,把他的Content-type设置为urlencoded这种模式,这样设置以后,在发送参数时,就可以在send里按照编码的方式来发送

后端代码


$name = $_POST[‘name’];
$age = $_POST[‘age’];
echo json_encode(array(
	‘name’ => $name,
	‘age’ => $age,
	‘money’=> 999999
));
?>

设置请求头信息

请求行和请求体在上述代码都可以进行设置

使用setRequestHeader方法可以设置请求头,该方法接受两个参数,一个是头的名字,一个是头的值。

xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')

Content-Type:设置请求体内容的类型

当然,也可以自定义请求体(仅了解)

xhr.setRequestHeader('Name','zhangsan');

此时由于浏览器的安全机制会发现报错,这个时候就需要后端加一个特殊的响应头,*表示所有类型的头信息后端都能接受

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

如果此时还不行,因为会发送一个校验检查这个头信息可不可用。此时,后端可以将app.post改为app.all(可以接收任何类型的请求)

JSON数据响应

前端

<body>
  <div id="result"></div>
  <script>
    //绑定键盘按下事件
    window.onkeydown = function () {
      const result = document.getElementById('result');
      //创建对象
      const xhr = new XMLHttpRequest();
      //设置响应体数据的类型(自动对数据进行转化)
      xhr.responseType = 'json';
      //初始化
      xhr.open('GET','http://127.0.0.1:3000/json-server');
      //发送
      xhr.send();
      //事件绑定
      xhr.onreadystatechange = function () {
        if(xhr.readyState === 4){
          if(xhr.status >= 200 && xhr.status < 300){
            // console.log(xhr.response);
            // result.innerHTML = xhr.response;

            //手动对数据转化
            // let data = JSON.parse(xhr.response);
            // console.log(data);
            // result.innerHTML = data.name;

            //自动转化
            console.log(xhr.response);
            result.innerHTML = xhr.response.name;

          }
        }
      }

    }
  </script>
</body>

手动对数据转化:使用parse()方法
自动对数据转化:设置响应体数据类型xhr.responseType = 'json';

后台

//1.引入express
const express = require('express');

//2.创建应用对象
const app = express();

//3.创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.all('/json-server',(request,response)=>{
  //设置响应头:设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*');

  //响应一个数据
  const data = {
    name: 'liming'
  }
  //对data对象进行字符串转换
  let str = JSON.stringify(data);

  //设置响应体
  //send方法里只能接受字符串和buffer
  response.send(str);
});

//4.监听端口启动服务
app.listen(3000,()=>{
  console.log('服务已经启动,3000端口监听中...');
})

AJAX-IE缓存问题

IE缓存问题:IE浏览器会对Ajax请求的结果做缓存,这样就会导致下次请求时的结果为本地的缓存,而不是最新数据。

解决方法:

发送请求时在url路径后面加一个时间戳,

xhr.open('GET','http://127.0.0.1:3000/ie?t='+Date.now());

原理:
Date.now():获取当前的时间戳
两次事件的时间戳不同,因此url也不同,那么浏览器就会认为这是两次不同的请求。这样,就会重新发一个新的请求,而不会去本地缓存中读取

AJAX请求超时与网络异常处理

请求超时回调:

xhr.ontimeout = function(){
    alert('网络异常,请稍后重试!!');
}

网络异常回调:

xhr.onerror = function(){
    alert('你的网络似乎出现了一些问题...')
}
btn.addEventListener('click',function () {
      const xhr = new XMLHttpRequest();
      //超时设置 (2s):如果2秒中之类,如果没有结果,那么这个请求就取消
      xhr.timeout = 2000;
      //超时回调
      xhr.ontimeout = function(){
        alert('网络异常,请稍后重试!!');
      }
      //网络异常回调
      xhr.onerror = function(){
        alert('你的网络似乎出现了一些问题...')
      }
      xhr.open('GET','http://127.0.0.1:3000/delay');
      xhr.send();
      xhr.onreadystatechange = function () {
        if(xhr.readyState === 4){
          if(xhr.status >= 200 && xhr.status < 300){
            result.innerHTML = xhr.response;
          }
        }
      }
    })

可以使用浏览器模拟网络问题:Offline断网
初学Ajax_第6张图片

AJAX取消请求

使用abort()方法

  <button>点击发送</button>
  <button>点击取消</button>
  <script>
    const btns = document.querySelectorAll('button');
    let xhr = null;
    btns[0].onclick = function () {
      xhr = new XMLHttpRequest();
      xhr.open('GET','http://127.0.0.1:8080/delay');
      xhr.send();
    }

    //取消请求
    btns[1].onclick = function () {
      xhr.abort();
    }
  </script>

AJAX重复发送问题

解决方法:设置一个标识符,做判断,将之间的请求取消掉

<button>点击发送</button>
<div id="result"></div>
<script>
  const btns = document.querySelectorAll('button');
  let xhr = null;

  //标识变量
  let isSending = false;//是否正在发送Ajax请求
  btns[0].onclick = function () {
    //判断标识变量:如果正在发送,就取消掉该(上一次)请求,创建新请求
    if(isSending)
      xhr.abort();
    xhr = new XMLHttpRequest();
    //修改标识符变量的值
    isSending = true;
    xhr.open('GET','http://127.0.0.1:3000/delay');
    xhr.send();
    xhr.onreadystatechange = function () {
      if(xhr.readyState === 4){
        //修改 标识变量的值
        isSending = false;
        if(xhr.status >= 200 && xhr.status < 300){
          result.innerHTML = xhr.response;
        }
      }
    }
  }

</script>

Axios发送AJAX请求

Fetch发送AJAX请求(看代码)

跨域

同源策略

同源策略:是浏览器的一种安全策略
同源:协议、域名、端口号必须完全相同

违背同源策略就是跨域

如何解决跨域

JSONP

  • jsonp是一个非官方的跨域请求方案,只支持get请求
  • 在网页中有一些标签天生具有跨域能力,比如:img link iframe script,jsonp就是利用script标签的跨域能力来发送请求的

CORS

  • CORS:跨域资源共享。CROS是官方的跨域解决方案
  • 特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理
  • 支持post,get请求。
  • HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
原理

CORS通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

你可能感兴趣的:(ajax,前端,http)