http,ajax,$.ajax,vue-resource,axios的知识大串联

前言

前端越来越工程化,而ajax是整个前端的核心,所以ES规则和各种封装的工具类越来越多;
借此机会我把http,XMLHttpRequest,ajax,$.ajax,vue-resource,axios做了一个知识大串联,本文主要是侧重将知识串成一条线,自己也复习下,希望也能帮到你们

1.http请求

1.1 什么是http

http是超文本传输协议英文简称,是基于TCP/IP通信协议来传递数据。

1.2三个特点

1.HTTP是无连接:每次只处理一个请求,处理完毕断开再处理下一个请求;
2.HTTP是媒体独立的:可以处理知道的能处理的数据类型,就是我们在请求的时候需要设置的请求头的内容,HTTP content-type内容
3.HTTP是无状态:就是没有办法记住上一次请求的状态;

1.3怎么解决无状态

1.由于很多需求是要记住上一次请求的状态信息,如登录状态的保持,所以要有对应的解决方案,那就是cookie和session
2.cookie简单的实现过程:后台通过req.header获取请求头的内容===>调用res处理===>cookie写入响应头===>返回数据写入响应体===>结束响应===>响应头响应体;
3.session实现过程:后台调用HttpServletRequest的getSession方法===>生成并发送给客户端session id,调用session相关方法增加内容===>客户端请求携带seession id===>服务端对应session id相应的Session,并重新创建session

1.4请求过程

域名解析 --> 发起TCP的3次握手(试探并建立TCP/IP连接) --> 建立TCP连接后发起http请求(请求行,请求头,请求主体) --> 服务器响应http请求(响应行,响应头,响应主体)-->四次挥手(中断这次TCP连接)

2 XMLHttpRequest

2.1定义:

是ajax的核心,提供了对 HTTP 协议的完全的访问,包括用get,post或head请求的能力,也就是可以理解为XMLHttpRequest对象里面对http协议请求进行了封装,并暴露一些属性和方法。

2.2属性:

1.readyState:XMLHttpRequest创建后方法调用的每个阶段对应的状态值,值为0-4,0-->创建对象,1-->请求行执行,2-->请求主体执行,3-->响应头已经接收完,响应主体正在接收,4-->请求完成
2.responseText:响应主体内容
3.responseXML:对请求的响应,解析为 XML 并作为 Document 对象返回。如果响应体不是“text/xml”返回null。
4.status:状态值
5.withCredentials:是一个布尔值, 默认为false, 表示跨域请求中不发送cookies等信息. 当它设置为true时, cookies , authorization headers 或者TLS客户端证书 都可以正常发送和接收. 显然它的值对同域请求没有影响.IE10才支持

2.3事件

onreadystatechange:readyState值改变会触发的事件句柄函数,主要就是监听该对象的每个阶段变化

2.4方法

1.abort():取消响应,如ajax中需要终止请求就是调用该方法,原理就是把 XMLHttpRequest 对象重置为 readyState 为 0 的状态
2.getAllResponseHeaders()/getResponseHeader():返回所有或单个的响应头

3.open(method,url,async,username,password):请求行。
method可以是get,post,head,put和delete,url一般是同源的(不同源就是常说的跨域);
async值默认是true(表示异步的),可以设置为false,表示同步;
username 和 password 参数是可选的,为 url 所需的授权提供认证资格

4.setRequestHeader("Content-type",format):设置请求头,如果请求行的方法是get可不设置
format值一般有四种(主要针对post提交):
默认纯文本:"text/plain; charset=utf-8",其中charset=utf-8可省略
json格式:"application/json"
表单默认:application/x-www-form-urlencoded,浏览器的原生 form 表单,如果不设置 enctype 属性就会以该格式提交,如果是form表单可设置enctype属性为multipart/form-data上传文件
html:text/html

4.send(data):请求主体,发送请求,如果请求行是get时data默认为空

2.5 版本

分为XMLHttpRequest Level 1和XMLHttpRequest Level 2
两者的不同看阮大哥的:XMLHttpRequest Level 2 使用指南

3.ajax

3.1 定义

全称Asynchronous Javascript And XML,实际上就是利用XMLHttpRequest 对象或者ActiveXObject(兼容IE)实现页面的局部请求数据功能。

3.2 请求实现

1.创建异步对象
let xhr = new XMLHttpRequest();//IE5和6是new ActiveXObject(),IE8,9是XDomainRequest()
2.请求行
xhr.open('get', url);//可以是get,post,head,put和delete
3.请求头(get可省略)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//格式见上面XMLHttpRequest请求头方法格式
4.监听响应头和主体
通过onreadystatechange 监听返回状态,通过XMLHttpRequest的getResponseHeader()判断响应头信息,得到对应的响应内容responseText或responseXML,代码如下

3.3 封装一个原生的ajax请求

/*
  type:请求方法
  data: 发送的数据
  url: 请求的url
  success:回掉函数
*/
ajax: function (option) {
  //1.创建异步对象
  var xhr = new XMLHttpRequest();
  //2.请求行
  if (option.type == 'get' && option.data) {
    option.url += '?';
    option.url += option.data;
    // 如果是get请求 那么 把data 设置为null 发送的时候 就相当于 发送null
    option.data = null;
  }
  xhr.open(option.type, option.url);
  //3.请求头(get请求可以省略)
  if (option.type == 'post' && option.data) {
    xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  }
  //4.注册状态改变事件
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200){
      let type = xhr.getResponseHeader('content-type');
      if (type.indexOf('json') != -1) {
       option.success(JSON.parse(xhr.responseText));
         return;
      }
      if (type.indexOf('xml') != -1) {
        option.success(xhr.responseXML);
        return;
      }
      option.success(xhr.responseText);
    }
  }

  //5.发送请求
  xhr.send(option.data);
}

3.4 get和post对比

1.发送数据形式不同:
get是拼接到URL后面,默认形式是QueryString,
post默认是Request Payload(因为XMLHttpRequest默认的请求头格式是text/plain),一般设置请求头设置了application/x-www-form-urlencoded就转化为From Data格式,
为什么要设置转化?Request Payload后台通过request.getParameter(name)无法获取数据
2.发送数据大小:
get是拼接到URl上的,IE对URL长度的限制是2083字节(2K+35字节),火狐和谷歌无限制,服务器可限制
post前端无限定大小,服务器可限制
3.安全性:
post比get安全,因为get是在URL中,所以数据暴露在外面,而且一般浏览器会缓存浏览的URL
如果要绝对的安全可以使用https传输

4. 跨域

4.1 什么叫跨域

就是不同源,同源指的是URL(统一资源定位符)的协议名,域名和端口名相同

4.2 同源限制的内容

Cookie、LocalStorage和IndexDB(浏览器自带的一个数据库)无法获取;
DOM无法获得;
AJAX请求不能发送;
所以同源策略设置的目的就是为了保证用户信息的安全,防止浏览器受到XSS、CSFR等攻击。

4.3 跨域常见的8种方式

一看8种,其实常用的只有三种,前面三种是比较常用的:

1.JSONP:就是利用<script>的src属性不受同源的限制,对应的用callback接收返回值;

2.CORS(跨域资源共享):
<1>简单请求:
http,ajax,$.ajax,vue-resource,axios的知识大串联
服务器设置:前端设置XMLHttpRequest的withCredentials为true,服务器设置Access-Control-
Allow-Credentials: true

<2>非简单请求:除了简单请求之外的,请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json
跨域方法:浏览器先预检,服务器回应
更多详情参照阮老师的跨域资源共享 CORS 详解

<3>反向代理:
原理:而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的

<4>WebSockets
WebSocket是HTML5新出的一种通信协议,是http协议支持长连接的一个优化,使用ws://(非加密)和wss://(加密)作为协议前缀。主要是该协议不实行同源政策,只要服务器支持
详情参照:WebSocket - Web API 接口 | MDN
大家有没想一个问题,WebScoket无同源限制难道不会有攻击吗?
其实那些跨域的URL是需要服务器授权的,没有授权的则无法访问.
详情参照:WebSocket通信协议应用安全问题分析

前面5种都是支持ajax请求的跨域方法
JSONP只适用于get方法做跨域,CORS和反向代理适用于所有请求方法;
JSONP适合所有浏览器,CORS只支持IE10及以上
WebSocket只能发送纯文本数据,所以如果发送复杂的格式的数据可以用JSON.STRINGFY来把数据序列化一下,而且有IE10及以上才支持

<5>document.domain + iframe 跨域:
只可以非同源共享cookie,DOM

<6>window.name + iframe 跨域

<7>跨文档通信API(Cross-document messaging)之window.postMessage
HTML5新引入的,可以跨域LocalStorage

<8>片段识别符
片段识别符指的是,URL的#号后面的部分,如果只是改变片段标识符,页面将不会重新刷新,父子窗口可以相互改变该标识符
详情参照:浏览器的跨域问题以及解决方案

5. ajax的几种封装类

5.1 $.ajax

常见的三种用法:
1.$.get

$.get(url,data,success(response,status,xhr),dataType)
    //data为传入的数据
    //"xml","html","text","script","json","jsonp",
    eg:
    $.get("test.cgi", { name: "John", time: "2pm" },
      function(data){
        alert("Data Loaded: " + data);
    });

2.$.post

$.post(url,data,success(data, textStatus, jqXHR),dataType)

3.$.ajax

$.ajax({
//常四个参数和一个回调函数
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

更多参数和回调函数见:jQuery ajax - ajax() 方法
4.三种对比
$.get和$post是$.ajax的简写形式,三种方法跨域的方法都是jsonp

5.2 fetch

1.语法

fetch(url, {
  method: "POST",//请求方法
  body: JSON.stringify(data),//请求主体
  headers: {
    "Content-Type": "application/json"//请求头
  },
  mode:cors,//请求的模式,值还可为no-cors 或者 same-origin
  credentials: "same-origin"//请求权限
}).then(function(response) {
  response.status     //=> 请求结果参数number 100–599
  response.statusText //=> 请求结果状态String
  response.headers    //=> 返回头部信息Headers
  response.url        //=> String

response.text()//方法还有json(),blob(),arrayBuffer(),formData()
.then(function(responseText) { ... })
}, function(error) {
  error.message //=> String
})

2.fetch的get使用

fetch(url)//options省略表示get
  .then(function(response) {
    return response.json();//生成json,
  }).then(function(data) {
    console.log(data);
  }).catch(function(e) {
    console.log("Oops, error");
  });

3.fetch的post使用

fetch('/users', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

fetch的详细使用:【译】fetch用法说明
4.fetch怎么实现跨域

mode的三个值的含义
same-origin:该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。
cors: 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求不需要后端额外的CORS支持;其对应的response-type为cors。
no-cors: 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;这也是fetch的特殊跨域请求方式;其对应的response-type为opaque
所以服务器支持则可以设置CORS,不支持可以设置no-cors

5.3 vue-resource

1.使用过程

/*安装*/
npm install vue-resource --save
/*引入Vue框架*/
import Vue from 'vue'
/*引入资源请求插件*/
import VueResource from 'vue-resource'
/*使用VueResource插件*/
Vue.use(VueResource)

2.$http.get

this.$http.get('/someUrl', [options]).then((response) => {
    // 响应成功回调
}, (response) => {
    // 响应错误回调
});

3.options参数值
http,ajax,$.ajax,vue-resource,axios的知识大串联

如果Web服务器无法处理PUT,PATCH和DELETE这种REST风格的请求,可以启用enulateHTTP现象。启用该选项后,请求会以普通的POST方法发出,并且HTTP头信息的X-HTTP-Method-Override属性会设置为实际的HTTP方法

3.$http.post
post请求默认的请求类型是request payload,根据上面get和post对比中提到request payload形式对后台获取数据不友好,所以需要将emulateJSON设置为true

4.拦截器(inteceptor)

Vue.http.interceptors.push({
request: function ( request ) {
    // 更改请求类型为POST
    request.method = 'POST';
    return request;
},
response: function ( response ) {
    // 修改返回数据
    response.data = [{
        custom: 'custom'
    }];
    return response;
}

});

5.跨域

JSONP:

Vue.http.jsonp(url,{params: {name='张三'},jsonp:"_callback"})
params是要发送的数据对象,jsonp是设置回调的名称,也就是上面的callback名称;(不设置默认为callback),后台获取发送过去的”_callpack”的值,将这个值拼接到返回的json数据上
CORS:
如果浏览器支持XMLHttpRequest Level 2在Broswer就可以设置
Vue.http.options.xhr = { withCredentials: true }
服务端启用支持
反向代理:在vue项目下的 config/index.js 文件里面配置代理proxyTable

5.4 axios

1.使用过程

/*安装*/
npm install axios --save
/*引入Vue框架*/
import Vue from 'vue'
/*引入资源请求插件*/
import axios from 'axios'
/*使用VueResource插件*/
Vue.use(axios)

2.axios.get

axios#get(url[,config])
axios.get(getUrl, {
    params: {
      'getAjaxDataObj1': getAjaxData.obj1,//obj1为getAjaxData的一个属性
      'getAjaxDataObj2': getAjaxData.obj2
    }
  }).then(data=>{
      //成功返回
  }).catch(err=>{
      //错误返回
  })

3.axios.post

axios#post(url[,config])
axios.post(postUrl, {
      'postAjaxDataObj1': postAjaxData.obj1,//obj1为postAjaxData的一个属性
      'postAjaxDataObj2': postAjaxData.obj2
  }).then(data=>{
      //成功返回
  }).catch(err=>{
      //错误返回
  })

4.axios.post请求的问题
默认请求数据格式是application/json,如果后台不支持这种form Data形式,则需要:

在Browser中
<1.>设置请求头格式
在config配置headers: {'X-Requested-With':'XMLHttpRequest'},
<2.>格式化数据
方法一:
并引入axios里面内置的qs,不需要重新下载
import qs from 'qs'
axios.post('/foo', qs.stringify({ 'bar': 123 }));
方法二:
let params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);

在node中
let querystring = require('querystring');//直接引入node的querystring模块
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));

4.config的常见参数:

//`url`是请求的服务器地址
  url:'/user',
  //`method`是请求资源的方式
  method:'get'//default
//如果`url`不是绝对地址,那么`baseURL`将会加到`url`的前面
  //当`url`是相对地址的时候,设置`baseURL`会非常的方便
  baseURL:'https://some-domain.com/api/',
//`headers`选项是需要被发送的自定义请求头信息
  headers: {'X-Requested-With':'XMLHttpRequest'},
//`withCredentails`选项表明了是否是跨域请求
  withCredentials:false,//default

详情请见:axios
4.axios的inteceptor(拦截器)

主要分为请求和响应两种拦截器,请求拦截一般就是配置对应的请求头信息(适用与常见请求方法,虽然ajax的get方法没有请求头,但是axios里面进行啦封装),响应一般就是对reponse进行拦截处理,如果返回结果为[]可以转化为0

axios.interceptors.request.use(config => {
  config.headers.cityCode = window.sessionStorage.cityCode //jsCookie.get('cityCode')
  return config
},
axios.interceptors.response.use((response) =>{
  let data = response.data
  if(response.request.responseType === 'arraybuffer'&&!data.length){
    reponse.date=0
  }
})

5.跨域
CORS:设置config里面的withCredentails为true
反向代理:和vue-resource一样
JSONP:axios里没有进行封装,但是github推荐了一种方法:
http,ajax,$.ajax,vue-resource,axios的知识大串联

详情请见:github中JSONP的实现

5.5为什么尤大大放弃维护vue-resource

我看了一下他的博客,大概意思是vue-resource之前是官方维护的,但是不同的路由和状态管理,ajax并不是一个问题域,需要与Vue核心深度整合,一个纯粹的第三方库能很好解决这个问题
原文链接(需要翻墙):Retiring vue-resource

5.6 ajax,$.ajax,vue-resource和axios对比

http,ajax,$.ajax,vue-resource,axios的知识大串联

结语

很开心你还能看到这里,整个文章概念还是挺多的,
希望这次梳理对你串联http,ajax,XMLHttpRequest,$ajax,vue-resource和axios有帮助。如果文章内容有错误欢迎指出交流!
可以先收藏着,想看的时候再慢慢体会。

参考文章:

http://www.runoob.com/http/ht...
http://www.ruanyifeng.com/blo...
http://www.ruanyifeng.com/blo...
https://developer.mozilla.org...
http://www.techweb.com.cn/net...
http://blog.csdn.net/u0130843...
http://www.w3school.com.cn/jq...
https://segmentfault.com/a/11...
https://www.jianshu.com/p/df4...
https://github.com/axios/axio...
https://medium.com/the-vue-po...

相关推荐