問題:異常統一處理
描述:
在大部分情況下,后台請求異常時,都會返回對應的狀態碼,400,404,500等等,但是,現在一些后端設計返回response.status都為200,通過code或者status來判斷請求是否正確,從而開始了這個坑的攻克。
問題處理:(此處用登錄狀態失效為例,status為3時登錄失效)
首先是發現了response.json()是一個promise,所以在處理的時候肯定是使用promise的方式來處理:
const res = response.json();
res.then(data => {
if (data.status === 3) {
const errortext = codeMessage[401];
const error = new Error(errortext);
error.name = response.status;
error.response = response;
throw error;
}
return data;
});
剛開始以為這樣處理就可以了,沒有return
這個promise
,所以在models里call了一個undefined,相當郁悶,所以開始走了一些歧路:
一直想着返回值是個Promise,所以就想着自己造一個
const res = response.json();
const promiseRes = res.then(data => {
const promise = new Promise((resolve) => {
if (data.status === 3 {
message.error('登錄狀態失效,請重新登錄', 3, () => {
window.g_app._store.dispatch({
type: 'login/logout',
});
});
}
resolve(data);
})
return promise;
})
return promiseRes;
雖然好像是解決了問題,但是又是resolve又是好幾層的return,怎么看都覺得別扭,但是由於項目忙就將就用了一段時間。
后來意識到了res本身就是一個promis,所以直接去掉了那一層別扭的promis(PS: 心里感覺各種舒暢)
const res = response.json();
return res.then(data => {
if (data.status === 3) {
const errortext = codeMessage[401];
const error = new Error(errortext);
error.name = response.status;
error.response = response;
throw error;
}
return data;
});
問題:fetch若進入catch會導致代碼出錯
描述:
這個問題產生於后台請求報常規錯誤時產生的,當后台返回狀態碼為500或者401后,進入catch,會發現antd pro 返回個啥,return;
???啥,這不就是返回了一個undefined么,然后導致了代碼報undefined的錯誤,更離譜的是,是401的時候,跳轉登錄,重新登錄后,出錯的列表頁,列表還是為空,甚至沒有重新請求接口。
問題解決:
解決辦法一: 使用神奇的 ...
put({
type: '',
payload: {
...response
}
});
// 同樣的在reduce里面也需要做相應的處理
return {
...state,
some: { ...payload }
}
解決辦法二:暴力解決,可能是一個不是辦法的辦法,但是好像有點卵用
return;
改成return e;
所以求一個更好的解決辦法,拜謝!!!
一些小問題:
1.當body的值是一個字符串時:
newOptions.body = JSON.stringify(newOptions.body); // 當為字符串的時候會有兩對引號
newOptions.body = typeof newOptions.body !== 'string' ? JSON.stringify(newOptions.body) : newOptions.body; // 所以加一個判斷
2.修改整體請求頭'Content-Type': 'application/x-www-form-urlencoded'
僅僅需要改成qs的stringify: s=1&a=2
import { stringify } from 'qs';
/*
* 此處省略
*/
newOptions.body = typeof newOptions.body !== 'string' ? stringify(newOptions.body) : newOptions.body;