Fetch和Axios的区别
[[toc]]
AJAX
const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { let keyText = xhr.responseText; console.log(keyText); } }; xhr.onprogress = function (event) { console.log(event.position); console.log(event.totalSize); }; xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/octet-stream"); xhr.setRequestHeader("Authorization", `UpToken ${uptoken}`); xhr.send({});
xhr.abort()
|
Axios
【 version:0.19.0 】
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; axios.defaults.headers.put['Content-Type'] = 'application/json'; axios.defaults.headers.delete['Content-Type'] = 'application/json';
const baseUrl = `${DEVURL}/shop/${id}/productOrders`; const CancelToken = axios.CancelToken; axios.post(baseUrl, { data, timeout: 3000, onUploadProgress:(progress)=>{ console.log(Math.round(progress.loaded / progress.total * 100) + '%'); }, cancelToken: new CancelToken(cancel=> { setTimeout(() => { console.log(cancel('取消请求')); }, 100) }) });
axios({ url: baseUrl, method: 'get', params: params, onDownloadProgress: (progress) => { console.log(Math.round(progress.loaded / progress.total * 100) + '%'); }, headers: { 'Content-Type': `application/octet-stream`, 'Authorization': `UpToken ` } });
const instance = axios.create({ baseURL: `${url}` }); instance.defaults.headers.common['Authorization'] = `Bearer ${getCookie('token')}`; axios.post(baseUrl,{data:{}})
|
配置axios
axios.interceptors.response.use(undefined, (err)=>{ const {config, code, response, message} = err; if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { notification['error']({ message: '连接超时', description: '正在重新为您请求数据!' });
return axios.request(config); } if (message === '取消请求') { notification['error']({ message: '已取消', description: '已您经取消此次提交!' }); return Promise.reject(err); } const {status, data: {error: msg}} = response; return (() => { notification['error']({ message: status, description: (response && msg) || HTTP_ERROR[status] }); return Promise.reject(err); })(); });
|
Fetch
fetch('http://xxxxx/xx.cn', { method: "POST", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: "q=参数q", cache?: RequestCache; credentials?: RequestCredentials; integrity?: string; keepalive?: boolean; mode?: RequestMode; redirect?: RequestRedirect; referrer?: string; referrerPolicy?: ReferrerPolicy; signal?: AbortSignal | null; window?: any; } )
|
Fetch vs Axios
浏览器支持
Fetch暂时不支持所有版本的IE
与成熟的XHR对象相比,Fetch API较新,预计未来几年会进行一定的维护工作,可能后期会返工。
你也可以选择将Fetch polyfill与Promise polyfill结合使用,以便在IE中执行Fetch代码
Fetch默认无Cookie
与XMLHttpRequest不同,Fetch并不会默认发送Cookie
,因此应用的身份验证可能会失败,可以通过更改第二个参数中传递的初始值来解决此问题。
fetch('http://xxxxx/xx.cn', { method: 'GET', credentials: 'same-origin' } )
|
错误不会被拒绝
HTTP错误(例如404 500)不会导致 Fetch返回的Promise标记为reject,.catch()也不会被执行。
想要精确的判断fetch是否成功,需要包含 promise.resolved 的情况,此时再判断 response.ok是不是为 true。
fetch('http://xxxxx/xx.cn', {method: 'GET'}).then(response => { if (response.ok) { return response.json(); } throw new Error('Network response was not ok.'); }).then(json => console.log(json)).catch(error => console.error('error:', error));
|
仅当请求无法完成时才触发reject,例如网络故障或请求被阻止。这会使错误捕获更加复杂。
不支持超时
Fetch不支持超时,只要浏览器允许,请求将继续。解决方法是可以将Fetch包装在一个 Promise中,例如:
const fetchTimeout = (url, init, timeout = 3000) => { return new Promise((resolve, reject) => { fetch(url, init).then(resolve).catch(reject); setTimeout(reject, timeout); }) };
|
或者 Promise.race([])
const fetchTimeout = (url, init, timeout = 30) => { return Promise.race( [ fetch(url, init), new Promise(resolve => setTimeout(resolve, timeout)) ] ).then(response => response.json()); };
|
中止Fetch
通过xhr.abort()很容易结束一个XHR请求,另外也可以通过xhr.onabort函数监测事件解决。
之前一直无法中止一个Fetch请求,但是现在实现了AbortController API的浏览器可以支持它。这将触发一个信号,该信号可以传递给Fetch启动对象:
AbortController接口代表一个控制器对象,允许你在需要时中止一个或多个DOM请求
const controller = new AbortController(); fetch('http://xxxx/xx.cn', { method: 'GET', signal: controller.signal }).then(response => response.json()) .then(json => console.log(json)) .catch(error => console.error('Error:', error));
|
可以通过调用 controller.abort() 来中止,Promise被标记reject后,会调用.catch()函数。
没有 progress
到目前为止Fetch仍不支持进度事件,因此,不可能显示文件上传或大型表单提交的进度状态。
参考文档
文档