問題解決
開發(fā)中我們可能會遇到展示文件上傳進(jìn)度的需求,原生的 XHR 請求是支持進(jìn)度回調(diào),axios 有 onUploadProgress 事件,而 fetch 不支持進(jìn)度。所以要留意一下你的公司內(nèi)部請求庫是基于哪個封裝的,才能順利使用進(jìn)度回調(diào)。
axios({ // 用法
url: 'http://...',
method: 'POST',
data: data,
onUploadProgress: handlerProgress
})
然而在實際項目中,我遇到了這種情況,正常使用 axios 的 onUploadProgress 事件沒問題,但是斷開網(wǎng)絡(luò)后,onUploadProgress 還是會有 loaded 進(jìn)度產(chǎn)生。于是上網(wǎng)搜索,axios 官方 issue 上也有人提過這個問題,但是沒有給出回答。而且,令我納悶的還有,在拔掉網(wǎng)線的情況下,我點擊上傳,network 下面的請求不是直接標(biāo)紅報網(wǎng)絡(luò)錯誤,而是 pendding 了好久才報錯。正常斷網(wǎng)不是應(yīng)該發(fā)布出去請求么,而且 onUploadProgress 居然還返回了已上傳了多少多少字節(jié)數(shù)據(jù)?
在我找到問題之前,我一度以為這是 axios 存在的 bug,后來才意識到可能是代理引起的。我的項目使用的是 umi 搭建,為了開發(fā)環(huán)境下實現(xiàn)跨域,我沒有選擇設(shè)置瀏覽器安全策略,而是選擇了 umi 提供的 proxy 代理。于是我的請求都是先請求了本地 localhost ,再由代理轉(zhuǎn)發(fā)到遠(yuǎn)程后端服務(wù),這樣一來就實現(xiàn)了跨域請求。
其實問題也不難被發(fā)現(xiàn),打開控制臺 network 查看,請求的 url 其實是本地的:

那就好理解了,前端發(fā)送上傳請求到本地,本地接收文件流的同時向服務(wù)器發(fā)送請求和文件流,在斷網(wǎng)的情況下,前端請求可以發(fā)送到本地,但是本地的發(fā)送不了給服務(wù)端,會報錯,導(dǎo)致請求失敗。onUploadProgress 僅有的一點已加載的數(shù)據(jù)其實是發(fā)送給本地服務(wù)的數(shù)據(jù)。這也就能解釋為什么 onUploadProgress 在斷網(wǎng)的情況下還能回傳進(jìn)度了。
關(guān)于跨域和反向代理
由于瀏覽器有同源策略,客戶端訪問和自己非同源的服務(wù)器(協(xié)議、ip、端口),如果不做任何設(shè)置,是會被拒絕的。解決跨域的方式很多:jsonp、iframe、瀏覽器設(shè)置、服務(wù)端設(shè)置響應(yīng)頭(CORS)、反向代理等等。這里說一下我對反向代理的理解。

關(guān)于正向代理和反向代理的區(qū)別:
- 正向代理:客戶端知道真正的服務(wù)器地址,而服務(wù)器不知道真正的客戶端是誰,只知道代理服務(wù)器地址;
- 反向代理:客戶端只管訪問代理服務(wù)器,而真實請求被代理到哪里是未知的;
實際上正向代理隱藏了真實的客戶端,而反向代理隱藏了真實的服務(wù)端。反向代理可以用來處理服務(wù)器的負(fù)載均衡以及解決跨域問題。
反向代理如何解決跨域問題:
在使用 Nginx 部署項目的時候,我們開啟某個端口對外提供服務(wù),但是用戶在訪問網(wǎng)站的時候,一般不會記得網(wǎng)站具體的端口,于是通常情況下我們都是將網(wǎng)站部署在默認(rèn)端口80下。但是后臺服務(wù)的地址肯定不會是 80,那這樣雖然前后端是在同一個ip下也會存在跨域。
Nginx 允許我們配置一個代理,將80端口下的特定路由的請求代理到對應(yīng)的真實服務(wù)器上,也就是說客戶端發(fā)送 /api/getInfo 這個請求的時候先訪問本地端口下的服務(wù),通過Nginx代理到了真實服務(wù)器上,并作出響應(yīng)。

不光 Nginx 可以做反向代理,前端框架像 Vue、umi 都可以配置反向代理來解決跨域問題,當(dāng)然這種配置是解決開發(fā)環(huán)境下的跨域問題(不用我們?nèi)ナ謩釉O(shè)置瀏覽器的屬性了)。