0Pricing
Frontend Academy · Lekcja

Wzorce interfejsów czasu rzeczywistego

Zastosuje Pan/Pani optymistyczne aktualizacje zapewniające natychmiastową informację zwrotną, użyje lokalnej kolejki offline i porówna napływające dane, aby aktualizować w interfejsie tylko zmienione elementy.

Wzorce interfejsów czasu rzeczywistego to bezpłatna lekcja Frontend Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Frontend Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Frontend Academy zawiera 4 lekcji w sumie.

Czas rzeczywisty to UX odczuwany jako natychmiastowy

Czas rzeczywisty to nie tylko szybkość — interfejs musi reagować przewidywalnie i łagodnie obsługiwać opóźnienia. Trzy podstawowe wzorce to optymistyczne aktualizacje, lokalne kolejkowanie i inteligentne porównywanie zmian.

Optymistyczne aktualizacje

Interfejs należy zaktualizować natychmiast po działaniu użytkownika, jeszcze przed potwierdzeniem przez serwer. Jeśli serwer odrzuci zmianę, należy ją wycofać. Dzięki temu aplikacja sprawia wrażenie natychmiastowej.

async function likePost(id) {
  // 1. Optimistically update UI:
  setLikes(l => ({ ...l, [id]: (l[id] || 0) + 1 }));
  setLiked(prev => ({ ...prev, [id]: true }));

  try {
    await fetch(`/api/posts/${id}/like`, { method: 'POST' });
  } catch (err) {
    // 2. Rollback on failure:
    setLikes(l => ({ ...l, [id]: (l[id] || 1) - 1 }));
    setLiked(prev => ({ ...prev, [id]: false }));
    toast.error('Could not like — please retry');
  }
}

Optymistyczne aktualizacje z tymczasowymi identyfikatorami

Tworzonym elementom należy lokalnie nadać tymczasowy identyfikator. Po otrzymaniu odpowiedzi należy zastąpić go rzeczywistym identyfikatorem z serwera.

async function addComment(text) {
  const tempId = `tmp-${Date.now()}`;
  setComments(c => [...c, { id: tempId, text, pending: true }]);

  try {
    const saved = await fetch('/api/comments', {
      method: 'POST',
      body: JSON.stringify({ text })
    }).then(r => r.json());

    setComments(c => c.map(m => m.id === tempId ? saved : m));
  } catch (err) {
    setComments(c => c.map(m => m.id === tempId ? { ...m, error: true } : m));
  }
}

Lokalne kolejkowanie w trybie offline

Gdy sieć jest niedostępna, działania należy umieszczać w lokalnej kolejce i odtworzyć je po przywróceniu połączenia. Użytkownik może nadal pracować.

const queue = JSON.parse(localStorage.getItem('queue') || '[]');

function enqueue(action) {
  queue.push(action);
  localStorage.setItem('queue', JSON.stringify(queue));
  trySend();
}

async function trySend() {
  while (queue.length && navigator.onLine) {
    const action = queue[0];
    try {
      await fetch(action.url, action);
      queue.shift();
      localStorage.setItem('queue', JSON.stringify(queue));
    } catch {
      break; // stop until online
    }
  }
}

window.addEventListener('online', trySend);

Porównywanie przychodzących danych czasu rzeczywistego

Jeśli serwer wysyła całą listę, należy porównać ją z bieżącym stanem i zaktualizować tylko zmienione elementy — pozwala to uniknąć niepotrzebnych ponownych renderowań i problemów z animacjami.

function applyServerSnapshot(newList, currentList) {
  const current = new Map(currentList.map(i => [i.id, i]));
  const result = newList.map(item => {
    const prev = current.get(item.id);
    if (!prev) return { ...item, _state: 'new' };
    if (prev.updatedAt !== item.updatedAt) return { ...item, _state: 'updated' };
    return prev;
  });
  return result;
}

Aktualizacje oparte na poprawkach

Są lepsze niż pełne migawki: serwer wysyła tylko zmienione pola. Należy stosować je przyrostowo — zużywają mniej pasma i szybciej są renderowane.

// Server sends: { type: 'patch', id: 42, fields: { likes: 11 } }
ws.on('message', (msg) => {
  if (msg.type === 'patch') {
    setPosts(posts => posts.map(p =>
      p.id === msg.id ? { ...p, ...msg.fields } : p
    ));
  }
});

Ograniczanie częstotliwości częstych aktualizacji

Niektóre strumienie wysyłają wiele aktualizacji na sekundę, na przykład pozycję myszy lub notowania giełdowe. Należy ograniczyć aktualizacje interfejsu do około 60 Hz, aby uniknąć zacinania przeglądarki.

import { throttle } from 'lodash-es';

const applyUpdate = throttle((data) => {
  setData(data);
}, 16); // ~60fps

ws.on('tick', applyUpdate);

Wskaźniki obecności

Należy pokazywać w czasie rzeczywistym, kto jeszcze jest online lub pisze. Serwer publikuje zdarzenia obecności, a klient renderuje listę z awatarami.

ws.on('presence', ({ users }) => {
  setOnlineUsers(users);
});

ws.on('typing', ({ user, isTyping }) => {
  setTypingUsers(t => isTyping
    ? [...t.filter(u => u.id !== user.id), user]
    : t.filter(u => u.id !== user.id));
});

Baner stanu połączenia

Należy wyświetlać subtelny baner w trybie offline lub podczas ponownego łączenia. Po pełnym przywróceniu połączenia należy go ukryć. Użytkownicy znacznie lepiej tolerują opóźnienia, gdy widzą, co się dzieje.

{!isConnected && (
  <div className="connection-banner">
    Reconnecting... Your changes will sync when you're back online.
  </div>
)}

Rozwiązywanie konfliktów

Aplikacje czasu rzeczywistego muszą obsługiwać równoczesne, sprzeczne zmiany. Strategie obejmują: last-write-wins (prosta, ale powodująca utratę danych), wektory wersji, OT (transformację operacyjną) i CRDT (Yjs, Automerge).

CRDT do współpracy

CRDTs (replikowane typy danych bez konfliktów) umożliwiają edycję w czasie rzeczywistym bez centralnego serwera. Biblioteki: Yjs, Automerge. Są używane w aplikacjach takich jak Figma, Linear i Notion.

Wydajność: wirtualizowane listy

Strumienie danych czasu rzeczywistego mogą znacznie się rozrosnąć. Należy używać wirtualizowanych list (react-virtuoso, @tanstack/react-virtual), aby renderować tylko widoczne elementy — pamięć i użycie procesora pozostają stałe niezależnie od całkowitej liczby elementów.

Szybkie sprawdzenie

Czym jest „optymistyczna aktualizacja” w interfejsie czasu rzeczywistego?

Podsumowanie: wzorce interfejsów czasu rzeczywistego

Optymistyczne aktualizacje sprawiają, że aplikacja wydaje się natychmiastowa; w razie niepowodzenia należy wycofać zmianę. Dla tworzonych elementów należy używać tymczasowych identyfikatorów. Lokalne kolejkowanie zapewnia trwałość działań offline. Aktualizacje serwera należy porównywać lub stosować jako poprawki, aby uniknąć ponownych renderowań. Częste strumienie należy ograniczać. Należy pokazywać obecność użytkowników (online, pisanie) i banery stanu połączenia. CRDT (Yjs, Automerge) służą do wspólnej edycji. Długie listy czasu rzeczywistego należy wirtualizować.

Często zadawane pytania

Czy lekcja „Wzorce interfejsów czasu rzeczywistego” jest bezpłatna?

Tak — pełny tekst „Wzorce interfejsów czasu rzeczywistego” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Frontend Academy, przejdź na CoddyKit PRO. Kurs Frontend Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorce interfejsów czasu rzeczywistego”?

Zastosuje Pan/Pani optymistyczne aktualizacje zapewniające natychmiastową informację zwrotną, użyje lokalnej kolejki offline i porówna napływające dane, aby aktualizować w interfejsie tylko zmienione… Ćwiczysz Frontend Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Frontend Academy?

Nie wymagamy żadnego doświadczenia. Frontend Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Wzorce interfejsów czasu rzeczywistego”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Frontend Academy?

Tak. Każda lekcja Frontend Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. WebSocket API: open, message, close, error
  2. Integracja klienta Socket.io
  3. Server-Sent Events do strumieniowania jednokierunkowego
  4. Wzorce interfejsów czasu rzeczywistego
← Powrót do Frontend Academy