axios和fetch的区别在于axios的response是一个综合各种方法的对象,并不是请求数据,需要经过处理后才能使用;fetch现在上没有取消请求的机制,axios存在取消请求的机制
fetch安装
为了解决 fetch 的兼容性,我们使用 Fetch Polyfill 的版本 whatwg-fetch。
npm install --save whatwg-fetch
import 'whatwg-fetch'
webpack 项目增加(加不加都可以)
entry: ['whatwg-fetch', ...]
也可以用另一个 fetch 版本
npm install --save isomorphic-fetch
fetch 的基本使用
fetch 是全局量 window 的一个方法, 第一个参数是URL:
// url (必须), options (可选)
fetch('/some/url', {
method: 'get'
}).then(function(response) {
}).catch(function(err) {
// 出错了;等价于 then 的第二个参数,但这样更好用更直观 :(
});
和 Battery API 类似, fetch API 也使用了 JavaScript Promises 来处理结果/回调:
// 链式处理,将异步变为类似单线程的写法: 高级用法.
fetch('/some/url').then(function(response) {
return //... 执行成功, 第1步...
}).then(function(returnedValue) {
// ... 执行成功, 第2步...
}).catch(function(err) {
// 中途任何地方出错...在此处理 :(
});
请求头(Request Headers)
自定义请求头信息极大地增强了请求的灵活性。我们可以通过 new Headers() 来创建请求头:
// 创建对象时设置初始化信息
var headers = new Headers({
'Content-Type': 'text/plain',
'X-My-Custom-Header': 'CustomValue'
});
// 添加(append)请求头信息
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');
// 判断(has), 获取(get), 以及修改(set)请求头的值
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');
// 删除某条请求头信息(a header)
headers.delete('X-My-Custom-Header');
headers 可以使用的方法包括: append, has, get, set, 以及 delete 。需要创建一个 Request 对象来包装请求头:
var request = new Request('/some-url', {
headers: new Headers({
'Content-Type': 'text/plain'
})
});
fetch(request).then(function(response) { /* handle response */ });
下面介绍 Request 和 Response 的使用方法!
Request 简介
Request 对象表示一次 fetch 调用的请求信息。传入 Request 参数来调用 fetch, 可以执行很多自定义请求的高级用法:
method - 支持 GET, POST, PUT, DELETE, HEAD
url - 请求的 URL
headers - 对应的 Headers 对象
body - 请求参数(JSON.stringify 过的字符串或 ‘name=jim&age=22’ 格式)
referrer - 请求的引用者(例如:client)
mode - 是否允许跨域请求,以及哪些响应的属性是可读的。可选值:
cors:(默认),允许跨域请求,将遵守 CORS 协议。
no-cors:该模式允许来自 CDN 的脚本、其他域的图片和其他一些跨域资源。前提条件是请求的 method 只能是 HEAD、GET 或 POST。此外,如果 ServiceWorkers 拦截了这些请求,它不能随意添加或者修改除这些之外 Header 属性。第三,js 不能访问 Response 对象中的任何属性,这确保了跨域时 ServiceWorkers 的安全和隐私信息泄露问题。
same-origin:如果是一个跨域请求,将返回一个 error。
navigate:支持导航的模式,仅用于 HTML 导航。
credentials - 设置 cookies 是否随请求一起发送。可选值:
omit:(默认),不发送 Cookie。
same-origin:同域下自动发送 Cookie。
include:始终发送 Cookie,即使是跨域。
redirect - 定义重定向处理方式。可选值:follow(默认), error, manual。
integrity - 子资源完整性值。
cache - 设置缓存模式。可选值:
default:浏览器在其 HTTP 缓存中查找匹配的请求。
a. 如果匹配并且是新鲜的,它将从缓存中返回。
b. 如果存在匹配但已失效,则浏览器将向远程服务器发出有条件的请求。如果服务器指出资源没有改变,它将从缓存中返回。否则资源将从服务器下载并且缓存将被更新。
c. 如果没有匹配,浏览器将发出正常的请求,并且下载的资源更新缓存。
no-store:浏览器从远程服务器获取资源,而不先查看缓存,并且不会使用下载的资源更新缓存。
reload:浏览器从远程服务器获取资源,而不先查看缓存,但随后将使用下载的资源更新缓存。
no-cache:浏览器在其 HTTP 缓存中查找匹配的请求。
a. 如果匹配,新鲜或陈旧,浏览器将向远程服务器发出有条件的请求。如果服务器指出资源没有改变,它将从缓存中返回。否则资源将从服务器下载并且缓存将被更新
b. 如果没有匹配,浏览器将发出正常的请求,并用下载的资源更新缓存。
force-cache:浏览器在其 HTTP 缓存中查找匹配的请求。
a. 如果有匹配,新鲜或陈旧,它将从缓存中返回。
b. 如果没有匹配,浏览器将发出正常的请求,并用下载的资源更新缓存。
only-if-cached:浏览器在其 HTTP 缓存中查找匹配的请求。只能用在 mode 为 same-origin 的情况下
a. 如果匹配,新鲜或陈旧,将从缓存中返回。
b. 如果没有匹配,浏览器将返回一个错误。
Request 的示例如下:
var request = new Request('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
});
// 使用!
fetch(request).then(function() { /* handle response */ });
只有第一个参数 URL 是必需的。在 Request 对象创建完成之后, 所有的属性都变为只读属性. 请注意, Request 有一个很重要的 clone 方法, 特别是在 Service Worker API 中使用时 —— 一个 Request 就代表一串流(stream), 如果想要传递给另一个 fetch方法,则需要进行克隆。
fetch 的方法签名(signature,可理解为配置参数), 和 Request 很像, 示例如下:
fetch('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
}).then(function() { /* handle response */ });
因为 Request 和 fetch 的签名一致, 所以在 Service Workers 中, 你可能会更喜欢使用 Request 对象。关于 ServiceWorker 的相关博客请等待后续更新!
提交表单数据(Posting Form Data)
另一种常用的 AJAX 调用是提交表单数据 —— 示例代码如下:
fetch('/submit', {
method: 'post',
body: new FormData(document.getElementById('comment-form'))
});
提交 JSON 的示例如下:
fetch('/submit-json', {
method: 'post',
body: JSON.stringify({
email: 'huang@163.com'
name: 'jim'
})
});
Response 简介
Response 代表响应, fetch 的 then 方法接收一个 Response 实例, 当然你也可以手动创建 Response 对象 —— 比如在 service workers 中可能会用到. Response 可以配置的参数包括:
type - 类型,支持: basic, cors
url - 响应的 URL
useFinalURL - Boolean 值, 说明这是否是响应的最终 URL
status - 状态码 (例如: 200, 404, 等等)
ok - Boolean值,代表响应是否成功(status 值在 200-299 之间)
statusText - 与状态码相对应的状态值(例如: OK为200)
headers - 与响应相关联的 Headers 对象.
redirected - 指示响应是否是重定向的结果。也就是说,它的 URL 列表有多条目录。
// 在 service worker 测试中手动创建 response
// new Response(BODY, OPTIONS)
var response = new Response('.....', {
ok: false,
status: 404,
url: '/'
});
// fetch 的 `then` 会传入一个 Response 对象
fetch('/')
.then(function(responseObj) {
console.log('status: ', responseObj.status);
});
Fetch 第一个 then 接受到的数据格式如下:
第二个 then 接收到的参数才是后台真正传过来的数据。
Response 提供的方法如下:
处理 JSON响应
假设需要请求 JSON —— 回调结果对象 response 中有一个json()方法,用来将原始数据转换成 json 对象:
fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) {
// 转换为 JSON
return response.json();
}).then(function(j) {
// 现在, `j` 是一个 json 对象
console.log(j);
});
当然这很简单 , 只是封装了 JSON.parse(jsonString) 而已, 但 json 方法还是很方便的。
处理基本的Text / HTML响应
JSON 并不总是理想的请求/响应数据格式, 那么我们看看如何处理 HTML或文本结果:
fetch('/next/page')
.then(function(response) {
return response.text();
}).then(function(text) {
// <!DOCTYPE ....
console.log(text);
});
如上面的代码所示, 可以在 Promise 链式的 then 方法中, 先返回 text() 结果 ,再获取 text 。
处理Blob结果
如果你想通过 fetch 加载图像或者其他二进制数据, 则会略有不同:
fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});
响应 Body mixin 的 blob() 方法处理响应流(Response stream), 并且将其读完。
未完的故事(Unwritten Story)
fetch 是个很实用的API , 当前还不允许取消请求, 这使得很多程序员暂时不会考虑它。
新的 fetch API 比起 XHR 更简单也更智能。毕竟,它就是专为AJAX而设计的, 具有后发优势. 而我已经迫不及待地使用了, 即使现在兼容性还不是那么好!
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征
引入方式
$ npm install axios
$ cnpm install axios //taobao源
$ bower install axios
或者使用cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
基本使用
GET请求
// 向具有指定ID的用户发出请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 也可以通过 params 对象传递参数
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
POST请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
//两个请求现已完成
}));
请求方法别名
为了方便起见,已经为所有支持的请求方法提供了别名。
axios.request(config)
axios.get(url [,config])
axios.delete(url [,config])
axios.head(url [,config])
axios.post(url [,data [,config]])
axios.put(url [,data [,config]])
axios.patch(url [,data [,config]])
拦截器
你可以截取请求或响应在被 then 或者 catch 处理之前
//添加请求拦截器
axios.interceptors.request.use(function(config){
//在发送请求之前做某事
return config;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});
//添加响应拦截器
axios.interceptors.response.use(function(response){
//对响应数据做些事
return response;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});
删除拦截器
var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
你可以将拦截器添加到axios的自定义实例
var instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
处理错误
axios.get('/ user / 12345')
.catch(function(error){
if(error.response){
//请求已发出,但服务器使用状态代码进行响应
//落在2xx的范围之外
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else {
//在设置触发错误的请求时发生了错误
console.log('Error',error.message);
}}
console.log(error.config);
});
您可以使用validateStatus配置选项定义自定义HTTP状态码错误范围
axios.get('/ user / 12345',{
validateStatus:function(status){
return status < 500; //仅当状态代码大于或等于500时拒绝
}}
})
消除
您可以使用取消令牌取消请求
可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel();
Vue.js是数据驱动的,这使得我们并不需要直接操作DOM,如果我们不需要使用jQuery的DOM选择器,就没有必要引入jQuery。vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。也就是说,$.ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。另外,vue-resource还提供了非常有用的inteceptor功能,使用inteceptor可以在请求前和请求后附加一些行为,比如使用inteceptor在ajax请求时显示loading界面。
vue2.0之后,就不再对vue-resource更新,而是推荐使用axios。
安装引入
$ cnpm install vue-resource
基础使用
引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http
// 基于全局Vue对象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
// 在一个Vue实例内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
在发送请求后,使用then方法来处理响应结果,then方法有两个参数,第一个参数是响应成功时的回调函数,第二个参数是响应失败时的回调函数。
then方法的回调函数也有两种写法,第一种是传统的函数写法,第二种是更为简洁的ES 6的Lambda写法:
// 传统写法
this.$http.get('/someUrl', [options]).then(function(response){
// 响应成功回调
}, function(response){
// 响应错误回调
});
// Lambda写法
this.$http.get('/someUrl', [options]).then((response) => {
// 响应成功回调
}, (response) => {
// 响应错误回调
});
支持的HTTP方法
get(url, [options])
head(url, [options])
delete(url, [options])
jsonp(url, [options])
post(url, [body], [options])
put(url, [body], [options])
patch(url, [body], [options])
options对象
参数 | 类型 | 描述 |
url | string | 请求的URL |
method | string | 请求的HTTP方法,例如:'GET', 'POST'或其他HTTP方法 |
body | Object, FormData string | request body |
params | Object | 请求的URL参数对象 |
headers | Object | request header |
timeout | number | 单位为毫秒的请求超时时间 (0 表示无超时时间) |
before | function(request) | 请求发送前的处理函数,类似于jQuery的beforeSend函数 |
progress | function(event) | ProgressEvent回调处理函数 |
credentials | boolean | 表示跨域请求时是否需要使用凭证 |
emulateHTTP | boolean | 发送PUT, PATCH, DELETE请求时以HTTP POST的方式发送,并设置请求头的X-HTTP-Method-Override |
emulateJSON | boolean | 将request body以application/x-www-form-urlencoded content type发送 |
response对象
方法 | 类型 | 描述 |
text() | string | 以string形式返回response body |
json() | Object | 以JSON对象形式返回response body |
blob() | Blob | 以二进制形式返回response body |
属性 | 类型 | 描述 |
ok | boolean | 响应的HTTP状态码在200~299之间时,该属性为true |
status | number | 响应的HTTP状态码 |
statusText | string | 响应的状态文本 |
headers | Object | 响应头 |