Улучшена логика проверки сетевого статуса в функции initOfflineMode, добавлены дополнительные проверки для определения оффлайн-режима. Обновлена обработка ошибок при создании заметок, добавлена логика для обработки сетевых ошибок и локального создания заметок. Оптимизирована функция checkNetworkStatus для более точного определения состояния сети с учетом таймаутов и различных типов ошибок.

This commit is contained in:
Fovway 2025-11-06 22:02:07 +07:00
parent 2c23044ea4
commit 351ba7eb03
3 changed files with 110 additions and 8 deletions

View File

@ -239,10 +239,62 @@ export const offlineNotesApi = {
store.dispatch(addNote(noteWithSyncStatus)); store.dispatch(addNote(noteWithSyncStatus));
return noteWithSyncStatus; return noteWithSyncStatus;
} catch (error) { } catch (error: any) {
console.error("Error creating note, falling back to local:", error); // Проверяем, является ли это сетевой ошибкой
// Fallback на локальное создание const isNetworkError =
return offlineNotesApi.create(note); !error.response &&
(error.code === 'ERR_NETWORK' ||
error.message === 'Network Error' ||
error.message?.includes('ERR_INTERNET_DISCONNECTED') ||
error.message?.includes('Failed to fetch'));
if (isNetworkError) {
console.error("Network error creating note, falling back to local:", error);
// Принудительно обновляем статус сети при ошибке
lastNetworkCheck = { time: Date.now(), status: false };
store.dispatch(setOfflineMode(true));
// Fallback на локальное создание напрямую, без рекурсии
console.log("[Offline] Creating note locally after network error");
const tempId = generateTempId();
const now = new Date().toISOString();
const newNote: Note = {
...note,
id: tempId,
user_id: userId || 0,
created_at: now,
updated_at: now,
is_pinned: 0,
is_archived: 0,
images: [],
files: [],
syncStatus: "pending",
};
// Сохраняем в IndexedDB
await dbManager.saveNote(newNote);
// Добавляем в очередь синхронизации
await dbManager.addToSyncQueue({
type: "create",
noteId: tempId,
data: note,
timestamp: Date.now(),
retries: 0,
});
// Обновляем UI
store.dispatch(addNote(newNote));
await updatePendingSyncCount();
return newNote;
} else {
// Если это не сетевая ошибка, пробрасываем её дальше
console.error("Error creating note (not a network error):", error);
throw error;
}
} }
}, },

View File

@ -24,7 +24,29 @@ async function initOfflineMode() {
console.log('[Init] IndexedDB initialized'); console.log('[Init] IndexedDB initialized');
// Проверка состояния сети // Проверка состояния сети
const isOnline = await checkNetworkStatus(); // Сначала проверяем navigator.onLine для быстрой проверки
let isOnline: boolean = navigator.onLine;
// Если navigator.onLine = false, точно оффлайн (не нужно делать fetch)
if (!navigator.onLine) {
isOnline = false;
} else {
// Если navigator.onLine = true, делаем дополнительную проверку через fetch
try {
isOnline = await checkNetworkStatus();
} catch (error) {
// Если проверка сети упала с ошибкой, скорее всего мы оффлайн
console.warn('[Init] Network status check failed, assuming offline:', error);
isOnline = false;
}
}
// Финальная проверка: если navigator.onLine = false, точно оффлайн
// Это важно, так как navigator.onLine может обновиться во время проверки
if (!navigator.onLine) {
isOnline = false;
}
store.dispatch(setOfflineMode(!isOnline)); store.dispatch(setOfflineMode(!isOnline));
console.log(`[Init] Network status: ${isOnline ? 'online' : 'offline'}`); console.log(`[Init] Network status: ${isOnline ? 'online' : 'offline'}`);

View File

@ -47,6 +47,7 @@ export async function checkNetworkStatus(): Promise<boolean> {
} }
// Дополнительная проверка через fetch с коротким таймаутом // Дополнительная проверка через fetch с коротким таймаутом
// Используем короткий таймаут для быстрого определения оффлайна
try { try {
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 2000); const timeoutId = setTimeout(() => controller.abort(), 2000);
@ -61,9 +62,36 @@ export async function checkNetworkStatus(): Promise<boolean> {
clearTimeout(timeoutId); clearTimeout(timeoutId);
return response.ok; return response.ok;
} catch (error) { } catch (error: any) {
// Если запрос не удался, но navigator.onLine = true, считаем что онлайн // Если запрос не удался, проверяем тип ошибки
// (возможно, просто таймаут или другая проблема) const isAbortError = error.name === 'AbortError'; // Таймаут
const isNetworkError =
error.message === 'Failed to fetch' ||
error.message?.includes('NetworkError') ||
error.message?.includes('ERR_INTERNET_DISCONNECTED') ||
error.message?.includes('ERR_NETWORK') ||
error.message?.includes('network request failed');
// Если это явная сетевая ошибка (не таймаут), точно оффлайн
if (isNetworkError && !isAbortError) {
return false;
}
// Если это таймаут, проверяем navigator.onLine
// Таймаут может быть как из-за оффлайна, так и из-за медленного соединения
if (isAbortError) {
// Если navigator.onLine = false, точно оффлайн
if (!navigator.onLine) {
return false;
}
// Если navigator.onLine = true, но таймаут - возможно медленное соединение
// Но для безопасности считаем оффлайном, так как запрос не прошел
return false;
}
// Если это не сетевая ошибка и не таймаут (например, CORS или другая проблема),
// но navigator.onLine = true, считаем что онлайн
// (возможно, просто другая проблема, но сеть есть)
return navigator.onLine; return navigator.onLine;
} }
} }