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