完成对请求失败的逻辑补充
This commit is contained in:
父節點
45df1f7409
當前提交
1b0e9d3042
@ -6,4 +6,4 @@
|
||||
请根据`env.example.json`的格式按照自己的需求编写`env.json`,或者直接运行`cp env.example.json env.json`,**否则无法正确处理网络请求!**
|
||||
|
||||
### 网络请求的用法
|
||||
引入./src/helper/axios.js(请以相对路径引入),尽情使用其中的post、get方法,它们会返回一个Promise(或可被视作Promise的AsyncFunction),且不会以抛出异常的方式通知网络错误,它会在服务器返回内容中插入属性`networkStatus`,**当值为200时才可以视作正确的服务器响应**,当值为-1时说明这是用户的网络错误,**你不需要处理200以外的情况,代码能够发出弹窗并建议用户重试**
|
||||
引入./src/helper/axios.js(请以相对路径引入),尽情使用其中的post、get方法,它们会返回一个Promise(或可被视作Promise的AsyncFunction),且为方便不会以抛出异常的方式通知网络错误。它会在服务器返回内容中插入属性`networkStatus`,**当值为200时才可以视作正确的服务器响应**,当值为-1时说明这是用户的网络错误。**你不需要处理200以外的情况,代码能够发出弹窗并建议用户重试**
|
@ -3,7 +3,7 @@ import { failed } from './alert';
|
||||
import qs from 'qs';
|
||||
import History from './history';
|
||||
|
||||
export function get(url) {
|
||||
export function get(url, evoker) {
|
||||
return send(
|
||||
axios.get(url, {
|
||||
headers: {
|
||||
@ -11,10 +11,13 @@ export function get(url) {
|
||||
"Allow-Control-Allow-Origin": "*"
|
||||
}
|
||||
}),
|
||||
{ fn: () => get(url), identifier: 'get:' + url }
|
||||
{
|
||||
fetcher: () => get(url, evoker),
|
||||
identifier: 'get:' + url + (evoker ? `@${evoker}` : '')
|
||||
}
|
||||
);
|
||||
}
|
||||
export function post(url, data) {
|
||||
export function post(url, data, evoker) {
|
||||
return send(
|
||||
axios.post(url, qs.stringify(data), {
|
||||
headers: {
|
||||
@ -22,7 +25,10 @@ export function post(url, data) {
|
||||
"Allow-Control-Allow-Origin": "*"
|
||||
}
|
||||
}),
|
||||
{ fn: () => post(url, data), identifier: 'post:' + url + ' ' + JSON.stringify(data) }
|
||||
{
|
||||
fetcher: () => post(url, data, evoker),
|
||||
identifier: 'post:' + url + (evoker ? `@${evoker}` : '')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -30,9 +36,19 @@ const waitToSend = [];
|
||||
|
||||
async function send(xhr, retryConf) {
|
||||
if (waitToSend.length) {
|
||||
if (waitToSend.every(retryConfItem => retryConfItem.identifier !== retryConf.identifier))
|
||||
waitToSend.push(retryConf);
|
||||
return;
|
||||
// 等待列表不为空,说明需要等待用户决定是否重试,这也提高了目前请求的成功率
|
||||
return await new Promise(res => {
|
||||
if (waitToSend.every(retryConfItem => retryConfItem.identifier !== retryConf.identifier))
|
||||
waitToSend.push({ ...retryConf, resolver: res });
|
||||
else
|
||||
waitToSend
|
||||
.filter(retryConfItem => retryConfItem.identifier === retryConf.identifier)
|
||||
.forEach(retryConfItem => {
|
||||
retryConfItem.resolver({ networkStatus: -2, status: false });
|
||||
retryConfItem.resolver = res;
|
||||
});
|
||||
// 虽然说理论上filter的结果只会有一个,但是还是要forEach一下,因为写起来方便hhhh
|
||||
});
|
||||
}
|
||||
try {
|
||||
const { data } = await xhr;
|
||||
@ -49,11 +65,18 @@ async function send(xhr, retryConf) {
|
||||
};
|
||||
if (err?.response?.status === 401) {
|
||||
History.force('/login');
|
||||
feedWaitList(failData);
|
||||
// 若是认证问题导致的错误,则没有必要继续后面等待的请求,且强制跳转后重试可能会导致已卸载的组件被更新
|
||||
return failData;
|
||||
}
|
||||
|
||||
if (!waitToSend.length) return failData;
|
||||
waitToSend.push(retryConf);
|
||||
// 等待列表不为空时弹框要么出现了要么就是在消失的路上,没有办法给予用户点击重试的机会,所以交由外部逻辑处理
|
||||
|
||||
// 注意,理论上带有时间戳的请求是不可以重试的,但是这里不做那方面考虑,如果未来有需要,可以自己实现一个刷新时间戳重试的逻辑
|
||||
if (err.message === 'Network Error')
|
||||
return await failed('您的设备似乎断网了,请检查网络后重试或刷新', flushWaitList) || failData;
|
||||
return await failed('您的设备似乎断网了,或者服务器发生了问题,请检查网络后重试或刷新', flushWaitList) || failData;
|
||||
if (!err?.response?.status)
|
||||
return await failed('请求发生问题:' + err.message, flushWaitList) || failData;
|
||||
if (err.response.status === 504)
|
||||
@ -63,7 +86,19 @@ async function send(xhr, retryConf) {
|
||||
}
|
||||
|
||||
function flushWaitList() {
|
||||
let fns = waitToSend.map(item => item.fn);
|
||||
let fns = waitToSend.map(
|
||||
conf =>
|
||||
async () => conf.resolver(await conf.fetcher())
|
||||
);
|
||||
waitToSend.splice(0, waitToSend.length);
|
||||
fns.forEach(fn => fn());
|
||||
}
|
||||
|
||||
function feedWaitList(data) {
|
||||
let fns = waitToSend.map(
|
||||
conf =>
|
||||
() => conf.resolver(data)
|
||||
);
|
||||
waitToSend.splice(0, waitToSend.length);
|
||||
fns.forEach(fn => fn());
|
||||
}
|
載入中…
x
新增問題並參考
Block a user