原生JS请求
现代浏览器,最开始与服务器交换数据,都是通过XMLHttpRequest对象。它可以使用JSON、XML、HTML和text文本等格式发送和接收数据。
首先我们先把原生的请求封装一下:
function obj2str(data) { data = data || {}; // 如果没有传参, 为了添加随机因⼦,必须⾃⼰创建⼀个对象 data.t = new Date().getTime(); var res = []; for (var key in data) { //在URL中是不可以出现中⽂的,如果出现了中⽂需要转码,可以调⽤encodeURIComponent⽅法,URL中 res.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key])); } return res.join("&"); } function ajax(option) { var str = obj2str(option.data);//key=value&key=value; var xmlhttp, timer; if (option.type.toLowerCase() === "get") {//toLowerCase将⼤写转化为⼩写 xmlhttp.open(option.type, option.url + "?" + str, true) xmlhttp.send(); } else { xmlhttp.open(option.type, option.url, true); //注意点:以下代码必须放在open和send之间 xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send(str); } xmlhttp.onreadystatechange = function (ev2) { if (xmlhttp.readyState === 4) { clearInterval(timer); //判断是否请求成功(Http状态码⼤于等于200,且⼩于300,和状态码等于304为请求成功) if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304) { option.success(xmlhttp); } else { option.error(xmlhttp); } } }; if (option.timeout) { timer = setInterval(function () { console.log("中断请求"); xmlhttp.abort(); clearInterval(timer); }, option.timeout); } }
使用:
ajax({ url:"http://server-name/login", type:'post', data:{ username:'username', password:'password' }, dataType:'json', timeout:10000, contentType:"application/json", success:function(data){ 。。。。。。//服务器返回响应,根据响应结果,分析是否登录成功 }, //异常处理 error:function(e){ console.log(e); } })
优点:
- 不重新加载页面的情况下更新网页
- 在页面已加载后从服务器请求/接收数据
- 在后台向服务器发送数据。
缺点:
- 使用起来也比较繁琐,需要设置很多值。
- 早期的IE浏览器有自己的实现,这样需要写兼容代码。
Jq中的ajax:
为了更快捷的操作DOM,并且规避一些浏览器兼容问题,产生了jQuery
。它里面的AJAX
请求也兼容了各浏览器,可以有简单易用的方法$.get
,$.post
。简单点说,就是对XMLHttpRequest
对象的封装。
$.ajax({ type: 'POST', url: url, data: data, dataType: dataType, success: function () {}, error: function () {} })
优点:
- 对原生
XHR
的封装,做了兼容处理,简化了使用。 - 增加了对
JSONP
的支持,可以简单处理部分跨域。
缺点:
- 如果有多个请求,并且有依赖关系的话,容易形成回调地狱。
- 本身是针对MVC的编程,不符合现在前端MVVM的浪潮。
- ajax是jQuery中的一个方法。如果只是要使用ajax却要引入整个jQuery非常的不合理。
Axios:
Axios
是一个基于promise
的HTTP
库,可以用在浏览器和 node.js
中。它本质也是对原生XMLHttpRequest
的封装,只不过它是Promise的实现版本,符合最新的ES规范。
axios({ method: 'post', url: '/user/12345', data: { firstName: 'liu', lastName: 'weiqin' } }) .then(res => console.log(res)) .catch(err => console.log(err))
优点:
- 从浏览器中创建
XMLHttpRequests
- 从
node.js
创建http
请求 - 支持
Promise
API - 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换
JSON
数据 - 客户端支持防御
XSRF
缺点:
- 只持现代代浏览器.
fetch:
Fetch API
提供了一个 JavaScript
接口,用于访问和操作HTTP
管道的部分,例如请求和响应。它还提供了一个全局fetch()
方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。fetch
是低层次的API,代替XHR
,可以轻松处理各种格式,非文本化格式。可以很容易的被其他技术使用,例如Service Workers
。但是想要很好的使用fetch
,需要做一些封装处理。
fetch('http://example.com/movies.json') .then(function(response) { return response.json(); }) .then(function(myJson) { console.log(myJson); });
fetch
目前遇到的问题:
-
fetch
只对网络请求报错,对400
,500
都当做成功的请求,需要封装去处理 -
fetch
默认不会带cookie
,需要添加配置项。 -
fetch
不支持abort
,不支持超时控制,使用setTimeout
及Promise.reject
的实现超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。 -
fetch
没有办法原生监测请求的进度,而XHR
可以。
请注意,fetch规范与jQuery.ajax()主要有两种方式的不同,牢记: -. 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。 -. 默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。