Skip to content

Commit 7faa91e

Browse files
committed
feat: implement getAllDataWithFallback function for improved data retrieval
1 parent 598f64f commit 7faa91e

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/components/List.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup>
2-
import { api, getStatusColor, getTagColor, getStatusIcon } from '@/utils.js';
2+
import { api, getStatusColor, getTagColor, getStatusIcon, getAllDataWithFallback } from '@/utils.js';
33
import { ref, onMounted, computed, watch } from 'vue';
44
import { useI18n } from 'vue-i18n';
55
import { useToast } from 'vue-toastification';
@@ -79,7 +79,7 @@ const toast = useToast();
7979
const listData = ref([]);
8080
const getData = async () => {
8181
loading.value = true;
82-
listData.value = await api("/all", "GET", toast);
82+
listData.value = await getAllDataWithFallback(toast);
8383
loading.value = false;
8484
};
8585

src/utils.js

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
export const api = async (path, method = "GET", toast = null, data = null, credentials = "include") => {
22
let baseUrl = "https://api.travellings.cn";
33
if (import.meta.env.DEV) {
4-
baseUrl = "/api";
4+
baseUrl = "/api";
55
}
6-
6+
77
const url = baseUrl + path;
88
const body = data ? JSON.stringify(data) : null;
99
const headers = {
@@ -15,18 +15,59 @@ export const api = async (path, method = "GET", toast = null, data = null, crede
1515
headers,
1616
credentials,
1717
});
18-
const resObj = await response.json();
18+
const resObj = await response.json();
1919
if (!resObj.success) {
2020
toast.error(resObj.msg);
2121
return null;
2222
}
2323
if (!resObj.data) {
2424
return resObj.msg;
2525
}
26-
26+
2727
return resObj.data;
2828
}
2929

30+
export async function getAllDataWithFallback(toast) {
31+
const primaryUrl = import.meta.env.DEV ? '/api/all' : 'https://api.travellings.cn/all';
32+
const backupUrl = 'https://backup.api.travellings.cn/list.json';
33+
const timeout = 10000;
34+
35+
const fetchWithTimeout = (url, timeoutMs) => {
36+
return Promise.race([
37+
fetch(url),
38+
new Promise((_, reject) =>
39+
setTimeout(() => reject(new Error('Request timeout')), timeoutMs)
40+
)
41+
]);
42+
};
43+
44+
try {
45+
const response = await fetchWithTimeout(primaryUrl, timeout);
46+
47+
if (!response.ok) {
48+
throw new Error(`HTTP Error ${response.status}: ${response.statusText}`);
49+
}
50+
51+
return await response.json();
52+
} catch (error) {
53+
console.warn('Primary API failed, trying backup:', error.message);
54+
toast.warning(`开往主服务器出现了故障(可能正在遭受攻击)。当前已自动使用备份的数据(可能并不是最新的)。
55+
The main server has malfunctioned (possibly under attack). Currently, backup data (which may not be the latest) has been automatically used instead.`);
56+
57+
try {
58+
const backupResponse = await fetchWithTimeout(backupUrl, timeout);
59+
60+
if (!backupResponse.ok) {
61+
throw new Error(`Backup API HTTP Error ${backupResponse.status}: ${backupResponse.statusText}`);
62+
}
63+
64+
return await backupResponse.json();
65+
} catch (backupError) {
66+
console.error('Both primary and backup APIs failed');
67+
throw new Error(`All APIs failed. Last error: ${backupError.message}`);
68+
}
69+
}
70+
}
3071
const statusIcon = {
3172
'LOST': 'exclamation-triangle',
3273
'WAIT': 'clock-o',

0 commit comments

Comments
 (0)