本文讲解浏览器请求的发展历程,从传统web应用到ajax,再到jquery,直到目前最为流行的axios。(重点详细讲,没用过的写个思想)
一、传统web应用
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页。过程是用户在客户端触发HTTP请求,服务器处理请求并返回新的HTHL页到客户端,客户端再重新读取整个页面。即使很小的交互,也要完成上述过程,导致浪费带宽且交互响应很慢。
在这个背景下,出现了可以更新部分网页数据的Ajax技术。
二、Ajax
1. 概念
AJAX即 Asynchronous JavaScript and XML。它不是新的编程语言,而是在不重新加载整个页面的情况下,与服务端交换数据并更新部分网页的技术。
2. 原理
Ajax 的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化,并且确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求,像—些数据验证和数据处理等都交给Ajax引擎自己来做,并不提交给服务端,提升性能。
3. 简单示例
Ajax 核心由 XMLHTTPRequest、JavaScript、DOM 对象组成,通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用 JavaScript 来操作 DOM 而更新页面。
const xmlHttp = new XMLHttpRequest()
// 发送请求
xmlHttp.open('GET', 'text1.txt', true) // open(method,url,async)
xmlHttp.send()
// 响应处理
xmlHttp.onreadystatechange = function () {
// 请求已完成,且响应就绪
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
document.getElementById('div1').innerHTML = xmlHttp.responsText
}
}
4. XMLHttpRequest对象
- readyState:存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。改变时触发onreadystatechange
- 0: 请求未初始化
- 1: 服务器连接已建立
- 2: 请求已接收
- 3: 请求处理中
- 4: 请求已完成,且响应已就绪
- status: 服务器的HTTP状态码
- 200: "OK"
- 404: 未找到页面
- ...
5. 优缺点
-
优点:
- 无刷新更新数据,用户体验提高
- 按需取数据,节约空间和带宽
- 部分工作转嫁到客户端,减轻服务器负担
- 基于标准被支持
-
缺点:
- 客户端变的复杂,容易出错
- 移动设备支持较差
- 安全问题
三、Jquery
1. 背景
因为不同的浏览器对 AJAX 的实现并不相同,所以编写统一的 AJAX 代码相对复杂。例如IE5、IE6没有XMLHttpRequest对象,而是ActiveXObject。
Jqury 库对 AJAX 进行了封装,使得我们可以通过更为简单统一的方式实现 AJAX 功能,同时能够把这些外部数据直接载入网页的被选元素中。
2. 主要 API 介绍
- $(selector).load(URL, data, callback): 从服务端获取获取并将数据载入到DOM元素中
- $.get(URL,callback) : 使用 GET 方法从服务端获取数据
- $.post( url [, data ] [, success ] [, dataType ] ) : 通过 HTTP POST 请求从服务器上请求数据。
- api详情
四、Fetch
1. Why fetch
传统ajax(指的是 XmlHttpRequest,即XHR)已经逐渐被Fetch替代。原因:
- Fetch语法简单,更加语义化, 并能方便的配置请求对象。
- 不需要引入jquery,且移动端支持较好
2. 简单示例
fetch(url).then(function(response) {
return response.json();
}).then(function(data) {
console.log(data);
}).catch(function(e) {
console.log("Oops, error");
});
// 使用 ES6 的 箭头函数 后:
fetch(url).then(response => response.json())
.then(data => console.log(data))
.catch(e => console.log("Oops, error", e))
3. polyfill: whatwg-fetch
fetch的原生支持并不好,通过引入polyfill来支持主流浏览器。实质是对于不支持 fetch api 的浏览器,使用 XMLHttpRequest 模拟实现 fetch api。
-
关键源码:
if (self.fetch) { return } ... self.fetch = function(input, init) { return new Promise(function(resolve, reject) { var request = new Request(input, init) var xhr = new XMLHttpRequest() xhr.onload = function() {...} } }
-
plato((项目采用的vue脚手架)引入方法:
// src/polyfills/index import 'whatwg-fetch' // webpack.config.bable.js entry: { app: [ paths.src('polyfills/index.js'), // 加载 polyfills paths.src('index.js')] // 加载入口 }
-
和Jquery.ajax()的区别
-
服务器返回 404,500 错误码时并不会reject,只有网络错误或者其他原因导致请求不能完成时,fetch 才会被 reject。为了保证reject HTTP错误状态,可做如下处理:eg:所有非2xx的错误码都抛出错误异常。 (----- 不好用,有时候需要做处理)
function checkStatus(response) { if (response.status >= 200 && response.status < 300) { return response } else { var error = new Error(response.statusText) error.response = response throw error } } function parseJSON(response) { return response.json() } fetch('/users') .then(checkStatus) .then(parseJSON) .then(function(data) { console.log('request succeeded with JSON response', data) }).catch(function(error) { console.log('request failed', error) })
-
plato(项目采用的vue脚手架)实现建request.js
const body = await getBody(res) if (res.status >= 200 && res.status < 400) { return body } else { throw body } async function getBody (res) { const type = res.headers.get('Content-Type') if (type && type.indexOf('json') !== -1) { return await res.json() } const body = await res.text() try { return JSON.parse(body) } catch (error) { return { body } } }
-
-
Fetch 请求默认是不带 cookie 的,而且也不接收cookie。
-
发送cookie
- 不跨域:fetch(url, {credentials: 'same-origin'})
- CORS 跨域请求:fetch(url, {credentials: 'include'})
-
接收cookie
同XHR相同, 从服务端返回的响应头Set-Cookie
是一个被禁的字段,所以不能通过response.headers.get()
来获取。获取cookie应该是浏览器的职责,通过document.cookie
来实现。
-
4. fetch() 详解
- 语法: Promise fetch(input[, init])
- 参数
- input:定义要获取的资源
USV字符串
,包含要获取资源的URL- Request对象
- init: 一个配置项对象,包括所有对请求的设置。可选的参数有:
- method
- headers
- body
- mode
- credientials
- cache
- ...
- input:定义要获取的资源
- 返回值: 一个 Promise,resolve 时回传 Response 对象。
五、Axios
基于Promise的HTTP库,用于浏览器端和Node.js端, 底层实现也是封装XMLHttpRequest。
-
Why axios:
- 支持两端:browser, nodejs
- 支持拦截器
- 支持json数据自动转换
- 基于promise,使用简单
- 体积小
- fetch 实现偏底层,通常需要封装后使用,axios可直接用
-
特点
- 浏览器端:make XMLHttpRequest
- Nodejs:make http request
- 支持promise api
- 支持请求 intercept、响应intercept
- 自动转换JSON数据
参考: