vue項(xiàng)目中使用fetch的實(shí)現(xiàn)方法
fetch的由來(lái)和定義
fetch的由來(lái)
眾所周知,傳統(tǒng) Ajax (指 XMLHttpRequest)是最早出現(xiàn)的發(fā)送異步請(qǐng)求技術(shù),其核心是使用XMLHttpRequest對(duì)象。但是它也存在一些令人頭疼的問(wèn)題:XHR 是一個(gè)設(shè)計(jì)粗糙的 API,不符合關(guān)注分離的原則;配置和調(diào)用方式非常混亂,而且基于事件的異步模型寫(xiě)起來(lái)也沒(méi)有現(xiàn)代的 Promise,generator/yield,async/await 友好。而Fetch 的出現(xiàn)就是為了解決 XHR 存在的問(wèn)題。
fetch的定義和使用
MDN中的描述:
Fetch API 提供了一個(gè)獲取資源的接口(包括跨域請(qǐng)求)。任何使用過(guò) XMLHttpRequest 的人都能輕松上手,但新的API提供了更強(qiáng)大和靈活的功能集。but 因?yàn)槠鄳K的兼容性,讓這個(gè)東東用起來(lái)比較困難。那我可以自己封裝一下,對(duì)于不支持fetch的瀏覽器便使用ajax 代替(見(jiàn)下文)。
Fetch 的核心在于對(duì) HTTP 接口的抽象,包括 Request,Response,Headers,Body,以及用于初始化異步請(qǐng)求的 global fetch。其中,global fetch方法的語(yǔ)法定義:
fetch(input[, init]);
input:定義要獲取的資源??梢允且粋€(gè)資源的 URL 字符串,也可以是一個(gè) Request 對(duì)象。
init:可選,一個(gè)配置項(xiàng)對(duì)象,包括所有對(duì)請(qǐng)求的設(shè)置。包括:method,headers,body,mode,credentials等返回值:Promise
切記一點(diǎn):Fetch是基于promise設(shè)計(jì)的,它不是ajax的進(jìn)一步封裝,而是原生js API,沒(méi)有使用XMLHttpRequest對(duì)象。
fetch的優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
1. 語(yǔ)法簡(jiǎn)潔,更加語(yǔ)義化
2. 基于標(biāo)準(zhǔn) Promise 實(shí)現(xiàn),支持 async/await
3. 同構(gòu)方便,更加底層,提供的API豐富(request, response, body , headers)5. 脫離了XHR,是ES規(guī)范里新的實(shí)現(xiàn)方式
缺點(diǎn):
1. fetch只對(duì)網(wǎng)絡(luò)請(qǐng)求報(bào)錯(cuò),對(duì)400,500都當(dāng)做成功的請(qǐng)求,服務(wù)器返回 400,500 錯(cuò)誤碼時(shí)并不會(huì) reject。
2. fetch默認(rèn)不會(huì)帶cookie,需要添加配置項(xiàng): credentials: 'include'。
3. fetch不支持abort,不支持超時(shí)控制,造成了流量的浪費(fèi)。
4. fetch沒(méi)有辦法原生監(jiān)測(cè)請(qǐng)求的進(jìn)度,而XHR可以
補(bǔ)充知識(shí)點(diǎn):
Fetch的mode配置項(xiàng)有3個(gè)取值:
same-origin:該模式是不允許跨域的,它需要遵守同源策略;
cors: 該模式支持跨域請(qǐng)求,顧名思義它是以CORS的形式跨域;
no-cors: 該模式用于跨域請(qǐng)求但是服務(wù)器不帶CORS響應(yīng)頭,也就是服務(wù)端不支持CORS;目前,針對(duì)跨域請(qǐng)求,cors模式是常見(jiàn)的實(shí)現(xiàn)。
vue項(xiàng)目中完美封裝fetch
話不多少,直接附上代碼。
env.js文件,如下:
/**
* baseUrl: 域名地址
* routerMode: 路由模式
*/
let baseUrl = '';
let routerMode = 'history';
if (process.env.NODE_ENV == 'development') {
baseUrl = 'http://localhost:3000';
}else{
baseUrl = 'http://xxxx這里是線上地址xxx';
}
export { baseUrl, routerMode }
fetch.js文件,如下:
import { baseUrl } from './env'
export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {
type = type.toUpperCase();
url = baseUrl + url;
// 此處規(guī)定get請(qǐng)求的參數(shù)使用時(shí)放在data中,如同post請(qǐng)求
if (type == 'GET') {
let dataStr = '';
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&';
})
if (dataStr !== '') {
dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
url = url + '?' + dataStr;
}
}
// 對(duì)于支持fetch方法的瀏覽器,處理如下:
if (window.fetch && method == 'fetch') {
let requestConfig = {
// fetch默認(rèn)不會(huì)帶cookie,需要添加配置項(xiàng)credentials允許攜帶cookie
credentials: 'include',
method: type,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
mode: "cors", // 以CORS的形式跨域
cache: "force-cache"
}
if (type == 'POST') {
Object.defineProperty(requestConfig, 'body', {
value: JSON.stringify(data)
})
}
try {
const response = await fetch(url, requestConfig);
const responseJson = await response.json();
return responseJson
} catch (error) {
throw new Error(error)
}
} else { // 對(duì)于不支持fetch的瀏覽器,便自動(dòng)使用 ajax + promise
return new Promise((resolve, reject) => {
let requestObj;
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest();
} else {
requestObj = new ActiveXObject; // 兼容IE
}
let sendData = '';
if (type == 'POST') {
sendData = JSON.stringify(data);
}
requestObj.open(type, url, true);
requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
requestObj.send(sendData);
requestObj.onreadystatechange = () => {
if (requestObj.readyState == 4) {
if (requestObj.status == 200) {
let obj = requestObj.response
if (typeof obj !== 'object') {
obj = JSON.parse(obj);
}
resolve(obj)
} else {
reject(requestObj)
}
}
}
})
}
}
以上代碼,親測(cè)有效。Over, thanks !希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue2.0 移動(dòng)端實(shí)現(xiàn)下拉刷新和上拉加載更多的示例
本篇文章主要介紹vue2.0 移動(dòng)端實(shí)現(xiàn)下拉刷新和上拉加載更多的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
基于vue實(shí)現(xiàn)滾動(dòng)條滾動(dòng)到指定位置對(duì)應(yīng)位置數(shù)字進(jìn)行tween特效
這篇文章主要介紹了基于vue實(shí)現(xiàn)滾動(dòng)條滾動(dòng)到指定位置對(duì)應(yīng)位置數(shù)字進(jìn)行tween特效,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
在 Vue3 中如何使用 styled-components
styled-components 的官方 Vue 版本目前已多年沒(méi)有更新,而且只支持到 Vue2,那么,在 Vue3 中怎么才能使用到 styled-components 呢,下面給大家介紹在 Vue3 中使用 styled-components的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2024-05-05
Vue新的狀態(tài)管理庫(kù)Pinia入門(mén)教程
Pinia不但支持Vue3,同時(shí)還支持Vue2,本文主要介紹了Vue新的狀態(tài)管理庫(kù)Pinia入門(mén)教程,具有一定的參考價(jià)值,感興趣的可以了解下2022-02-02
vue項(xiàng)目使用$router.go(-1)返回時(shí)刷新原來(lái)的界面操作
這篇文章主要介紹了vue項(xiàng)目使用$router.go(-1)返回時(shí)刷新原來(lái)的界面操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
vue常用指令實(shí)現(xiàn)學(xué)生錄入系統(tǒng)的實(shí)戰(zhàn)
本文主要介紹了vue常用指令實(shí)現(xiàn)學(xué)生錄入系統(tǒng)的實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
解決vue中對(duì)象屬性改變視圖不更新的問(wèn)題
下面小編就為大家分享一篇解決vue中對(duì)象屬性改變視圖不更新的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

