AJAX基础知识

168 阅读4分钟

AJAX基础知识:核心原理是基于XMLHttpRequest实现前后端数据通信的

面试题:Ajax中有多少个方法?

   私有属性
   可以监听的事件
   + onabort  请求被中断触发
   + onreadystatechange  监听Ajax的状态改变(根据不同的状态处理不同的事情)
   + ontimeout  请求超时后触发
   + upload.onprogress  监听文件上传或者下载的进度
   常规属性
   + readyState  记录ajax状态
   + status/statusText  服务器返回的HTTP状态码及其描述
   + timeout  设置超时时间(MS),默认0代表不设置:如果设置了超时时间,在这个期间内,如果请求没有结束,则自动中断,触发ontimeout事件
   + withCredentials  在“跨域”请求中,设置是否允许携带资源凭证(例如:cookie),默认false
   + response  存储服务器返回的响应主体信息(不论啥格式)
   + responseText  存储格式为字符串的响应主体信息
   + responseXML  存储格式为XML的响应主体信息
   + ...

 公共方法
   + open() 打开请求连接(在发送请求之前进行一些配置)
   + send([body]) 发送请求,并且基于请求主体把信息传递给服务器
   + setRequestHeader([key],[value]) 设置请求头信息{传递的值不能有中文,如果有需要编码}
     + 转码的三种方式
      + escape
      + encodeURI
      + encodeURIComponent
   + overrideMimeType() 重写MIME类型
   + getAllResponseHeaders() / getResponseHeader([key]) 获取所有(某一个)响应头信息
   + abort() 中断当前请求
   ----
   代表Ajax状态(xhr.readyState)的五个属性
   + UNSENT: 0  未发送(最开始创建出XHR实例的初始状态)
   + OPENED: 1  已经执行了open这个方法
   + HEADERS_RECEIVED: 2  请求已经发送,并且获取到了响应头信息
   + LOADING: 3  响应主体信息正在返回中
   + DONE: 4  响应主体信息已经返回(当前Ajax请求结束)

Ajax核心操作:

@1 ajax:async javascript and xml 「了解」

+ async javascript:不仅仅是异步请求,更主要的是“局部刷新”
+ xml:很早很早以前,Ajax从服务器获取的数据格式一般都是XML格式的,只不过目前我们都是基于体积更小、操作更方便的JSON格式进行传输!!

@2 请求方式:GET系列 & POST系列 GET系列:GET/HEAD/DELETE/OPTIONS POST系列:POST/PUT/PATCH ---

不论GET还是POST,客户端都可以在发请求的时候,把信息传递给服务器,服务器也可以把信息返回客户端;
  客户端->服务器
  + URL问号传参  '/user/list?xxx=xxx&xxx=xxx'
  + 设置请求头  xhr.setRequestHeader(xxx,xxx);
  + 设置请求主体  xhr.send(xxx);
  服务器->客户端
  + 设置响应头
  + 设置响应主体 「响应头信息会比响应主体先发返回」
---
约定俗成的规范:GET系列请求,一般都是基于“URL问号传参”把信息传递给服务器;而POST系列请求,一般是基于请求主体把信息传递给服务器;两种方式都可以设置请求头信息!!
  + 传递给服务器信息的大小
    + GET是基于URL传参,而浏览器对于URL的长度有限制(IE:2KB、谷歌:8KB、火狐:7KB...),所以GET传递给服务器的信息要少!!
    + POST是基于请求主体传递信息,理论上是没有任何长度限制的「实际开发中,我们自己做限制」
  + 安全方面
    + 互联网面前,人人都在“裸奔”,没有绝对的安全
    + POST比GET相对安全一些:因为有一种很好实现的“黑客”技术--URL劫持,而GET是URL传参,一旦被劫持,则信息泄露;而请求主体的信息不容易被劫持!
  + 缓存问题
    + 还是因为GET是URL传参,如果多次请求:地址+传递参数值 都完全一致,浏览器可能会帮我们获取上一次缓存中的信息,导致无法实时获取最新的信息!
      解决:保证每一次请求传递的参数值不完全一致即可
      xhr.open('GET',`/user/list?xxx=xxx&_=${+new Date()}`);
---
基于请求主体传递给后台的内容有“格式要求”:每一种格式都有相关的描述,我们称之为MIME类型
  + JSON格式的字符串  MIME:application/json
    '{"name":"xxx","age":25,...}'
  + URLENCODED格式字符串  MIME:application/x-www-form-urlencoded
    'xxx=xxx&xxx=xxx&...'
  + FORM-DATA格式对象  MIME:multipart/form-data {一般用于文件上传}
    let fm=new FormData();
    fm.append('name','xxx');
    fm.append('file',...);
    xhr.send(fm);
  + 普通格式字符串 MIME:text/plain
  + 传递Buffer(进制)格式的数据
  + ...
  ---
  如果传递的是普通对象,浏览器也会默认转换为“[object Object]”传递给服务器!!
  当我们基于xhr.send请求主体,发送信息给服务器的时候,根据我们传递的数据格式,需要手动设置请求头:xhr.setRequestHeader('Content-Type',对应的MIME类型)

@3 设置请求头的操作必须在:OPEND之后和SEND之前;而且设置请求头的信息不能出现中文,如果需要传递中文,则需要编码「encodeURIComponent / encodeURI」

@4 xhr.status记录服务器返回的HTTP响应状态码:不同的状态码描述了请求成功或者失败 + xhr.status:HTTP响应状态码 (服务器基于不同的状态码告知客户端相应的结果)

  + 以2开始的基本上都是成功
    + 200 Ok 标准成功
    + 206 Partial Content 断点续传
  + 以3开始的虽然也获取到数据了,但是中间会经历一些特殊的处理
    + 301 Moved Permanently 永久转移(永久重定向)===>域名迁移
    + 302 (307) Move Temporarily 临时转移(临时重定向)===>服务器负载均衡
    + 304 Not Modified 服务器资源未更新(协商缓存)
  + 以4开始的一般都是客户端错误
    + 400 Bad Request 参数错误
    + 401 Unauthorized 权限有问题
    + 403 Forbidden  服务器拒绝你的请求,但是为啥不告诉你,因为原因很多
    + 404 Not Found 地址错误
    + 405 Method Not Allowed  请求的方式不被允许
    + 408 Request Timeout 请求超时
  + 以5开始的一般都是服务器错误
    + 500 Internal Server Error 未知服务器错误
    + 502 Bad Gateway  网管或者代理服务器出现了问题
    + 503 Service Unavailable  超负荷 
let xhr = new XMLHttpRequest;
xhr.open('GET', './package.json');
xhr.timeout = 10000;
xhr.withCredentials = true;
xhr.setRequestHeader('name', encodeURIComponent('珠峰培训'));
xhr.onreadystatechange = () => {
    let { readyState, status } = xhr;
    if (!/^(2|3)\d{2}$/.test(status)) {
        // 状态码出现问题:本次请求失败
        return;
    }
    // 服务器正常返回信息了
    if (readyState === 2) {
        // 响应头信息已经有了:获取的服务器时间是格林尼治时间,我们需要变为北京时间
        let serverTime = xhr.getResponseHeader('date');
        console.log('服务器时间:', new Date(serverTime));
    }
    if (readyState === 4) {
        // 响应主体信息已经有了,常见的响应主体信息的格式
        // + JSON字符串「最常用的」
        // + XML格式的数据  xhr.responseXML
        // + Buffer格式的数据
        // + ...
        let data = JSON.parse(xhr.responseText);
        console.log('响应主体:', data);
    }
};
xhr.onerror = () => {
    // 进入这里一般是网络问题
};
xhr.send(); 

真实项目中,我们应用的是把Ajax进行封装的插件/库

  • JQ :基于回调函数方式管理
  • Axios :基于Promise管理
$.ajax({
  url: './package.json',
  method: 'GET',
  dataType: 'json', //把从服务器获取的响应主体信息,转换为指定的格式
  cache: true, //GET系列请求是否设置缓存 false去掉缓存
  data: { //GET系列请求,会把对象中的信息以URL问号传参传递给服务器;POST系列请求,会作为请求主体传递给服务器(会把对象默认变为URLENCODED字符串处理)!
      name: 'xxx',
      age: 25
  },
  success(value) {
      console.log('成功:', value);
  },
  error(reason) {
      // HTTP状态码不是2开头、网络出问题、请求中断/超时...
      console.log('失败:', reason);
  }
});