Wyjaśnienie pętli zdarzeń JavaScript: stos wywołań, mikrozadania i liczniki czasu z przykładami

  1. Strona główna
  2. Blog
  3. Rozwój oprogramowania

Rozwój oprogramowania

Wyjaśnienie pętli zdarzeń JavaScript: Stos wywołań, mikrozadania i liczniki czasu z przykładami

Dlaczego setTimeout o wartości zerowej nadal działa jako ostatni? Jak jeden wątek może obsłużyć tak wiele na raz? Dowiedz się, jak naprawdę działa pętla zdarzeń, przetestuj ją za pomocą uruchomionego przez nas kodu i rozwiąż klasyczne pytanie podczas rozmowy kwalifikacyjnej.

9 min czytania
Wyjaśnienie pętli zdarzeń JavaScript: stos wywołań, mikrozadania i timery z przykładami

Najważniejsze

  • JavaScript uruchamia Twój kod w pojedynczym wątku, po jednym fragmencie na raz.
  • Gdy stos wywołań jest pusty, najpierw uruchamiane są wszystkie mikrozadania, a następnie jedno zadanie.
  • setTimeout(fn, 0) oznacza „jak najszybciej po minimalnym opóźnieniu”, a nie „teraz”.
  • Długa praca synchroniczna blokuje wszystko, więc podziel ją lub przenieś do pracownika.

Uruchom kilka linii z setTimeout i obietnicą, a kolejność wyników może Cię zaskoczyć. Pętla zdarzeń JavaScript wyjaśnia dlaczego. Jest to mechanizm, który pozwala językowi jednowątkowemu obsługiwać liczniki czasu, połączenia sieciowe i kliknięcia bez zawieszania się.

Kiedy to zrozumiesz, cała klasa mylących błędów zacznie mieć sens. Każdy przykład uruchomiliśmy w Node.js 24, a dane wyjściowe pochodzą z tego uruchomienia. Podstawowe zasady porządkowania obowiązują również w przeglądarkach i wskazujemy, czym różni się Node.js. Zyskasz na tym więcej, jeśli znasz już podstawy obietnic JavaScript.

Dlaczego istnieje pętla zdarzeń

JavaScript wykonuje kod w jednym głównym wątku, więc w danym momencie działa tylko jeden jego fragment. Gdyby po prostu czekała na żądanie sieciowe, strona zawieszałaby się do czasu otrzymania odpowiedzi.

Zatem JavaScript nie czeka. Wolna praca przekazywana jest środowisku hosta, czyli przeglądarce lub Node.js, która radzi sobie z nią w tle. Po zakończeniu tej pracy wywołanie zwrotne jest umieszczane w kolejce. Zadaniem pętli zdarzeń jest przenoszenie wywołań zwrotnych z kolejki na stos, gdy jest on wolny.

Pomyśl o szefie kuchni pracującym samotnie. Szef kuchni zamiast się na nie gapić, wkłada danie do piekarnika i ustawia minutnik. Kiedy zadzwoni minutnik, zadanie trafia na listę, a szef kuchni podejmuje się go po skończeniu tego, co aktualnie jest w zasięgu ręki.

Ruchome części

Część Co to robi Przykłady
Stos wywołań Śledzi aktualnie uruchomione funkcje Twój kod synchroniczny
Interfejsy API hosta Pracuj poza swoim kodem Timery, fetch, odczyty plików
Kolejka zadań Przechowuje wywołania zwrotne, które są gotowe do uruchomienia setTimeout, kliknięcia, we/wy
Kolejka mikrozadań Przechowuje wywołania zwrotne o wyższym priorytecie .then, await, queueMicrotask
Pętla zdarzeń Decyduje, co będzie dalej Działa nieprzerwanie

Zadania są czasami nazywane makrozadaniami. Ściśle mówiąc, może istnieć kilka źródeł zadań, a dokładne szczegóły różnią się w zależności od środowiska.

Zasady

  1. Uruchamiaj cały kod synchroniczny, aż stos wywołań będzie pusty.
  2. Uruchamiaj wszystkie mikrozadania, łącznie z nowymi dodanymi po drodze.
  3. W przeglądarce wyrenderuj aktualizację, jeśli jest ona wymagana.
  4. Weź jedno zadanie z kolejki i uruchom je.
  5. Wróć do kroku 2.

Najważniejszy szczegół: wszystkie mikrozadania, a następnie jedno zadanie. Większość zagadek z pętlą zdarzeń rozwiązuje się, stosując tę ​​pojedynczą regułę.

Zobacz zamówienie

console.log("1 sync");
setTimeout(() => console.log("5 timeout"), 0);
Promise.resolve().then(() => console.log("3 promise"));
queueMicrotask(() => console.log("4 microtask"));
console.log("2 sync");

// 1 sync
// 2 sync
// 3 promise
// 4 microtask
// 5 timeout

Oto co się stało. Dwie console.log linie są synchroniczne, więc biegły jako pierwsze. Obietnica wywołania zwrotnego i queueMicrotask weszły do ​​kolejki mikrozadań i zostały uruchomione, gdy tylko stos się opróżnił, w kolejności, w jakiej zostały dodane. Wywołanie zwrotne timera musiało czekać na turę zadania, mimo że jego opóźnienie wynosiło zero.

Mikrozadania działają pomiędzy timerami

Po każdym pojedynczym zadaniu kolejka mikrozadań jest ponownie opróżniana. Ten przykład to potwierdza:

setTimeout(() => {
  console.log("timer 1");
  Promise.resolve().then(() => console.log("promise inside timer 1"));
}, 0);
setTimeout(() => console.log("timer 2"), 0);

// timer 1
// promise inside timer 1
// timer 2

Obietnica, która została utworzona podczas pierwszego licznika czasu, działała przed drugim licznikiem czasu. Nowoczesne przeglądarki i Node.js 11 i nowsze zachowują się w ten sposób.

Gdzie czekać pasuje

await dzieli funkcję na dwie części. Wszystko przed nim działa synchronicznie, a wszystko po nim jest zaplanowane jako mikrozadanie. To zaskakuje wiele osób:

async function task() {
  console.log("A before await");
  await null;
  console.log("C after await");
}

task();
console.log("B after calling task");

// A before await
// B after calling task
// C after await

Funkcja async nie jest uruchamiana w tle. Działa w tym samym wątku, aż dotrze do pierwszego await. Dotyczy to nawet sytuacji oczekiwania na coś, co nie jest prawdziwą obietnicą, jak na przykład null. Więcej informacji na temat tej składni znajdziesz w naszym przewodniku po asynchronizacji/oczekiwaniu JavaScriptu.

Blokowanie pętli

Podczas działania kodu synchronicznego nic innego nie może. Aby to pokazać, ustawiliśmy timer na 0 ms, a następnie utrzymywaliśmy wątek zajęty przez pół sekundy:

const start = Date.now();
setTimeout(() => console.log("timer ran after", Date.now() - start, "ms"), 0);
while (Date.now() - start < 500) {}

// timer ran after about 500 ms

Opóźnienie timera jest minimalnym, a nie gwarancją. Działał tylko wtedy, gdy stos stał się wolny. Na stronie internetowej taka długa pętla oznacza, że ​​kliknięcia nie odpowiadają, a animacje się zatrzymują. Na serwerze każde inne żądanie musi poczekać, dlatego jedno wolne wywołanie synchroniczne może zaszkodzić wszystkim użytkownikom procesu Node.js.

Typowe przyczyny blokowania obejmują ogromne pętle, analizowanie bardzo dużych plików JSON, synchroniczne funkcje plików, takie jak readFileSync w procedurach obsługi żądań i katastrofalne wyrażenia regularne.

Wskazówka: w Chrome DevTools panel Wydajność oznacza zadania dłuższe niż 50 ms jako zadania długie. To szybki sposób na znalezienie przyczyny spowolnienia strony.

Zachowując responsywność

W przypadku ciężkiej pracy daj pętli zdarzeń szansę odetchnąć. Jednym ze sposobów jest wstrzymywanie od czasu do czasu timera, co pozwala na uruchomienie innych zadań:

const items = [0, 1, 2, 3, 4];

async function processAll() {
  for (const item of items) {
    if (item === 2) await new Promise((r) => setTimeout(r, 0));
    console.log("item", item);
  }
}

setTimeout(() => console.log("other work gets a turn"), 0);
processAll();

// item 0
// item 1
// other work gets a turn
// item 2
// item 3
// item 4

Drugi timer pobiegł w środku, bo ustąpiliśmy przed prawdziwym zadaniem. Prawdziwy kod dawałby co określoną liczbę elementów lub milisekund. W przypadku pracy naprawdę obciążającej procesor, takiej jak przetwarzanie obrazów, użyj procesu roboczego sieci Web w przeglądarkach lub wątku roboczego w Node.js, który działa w oddzielnych wątkach.

Głód mikrozadań

Ponieważ pętla całkowicie opróżnia kolejkę mikrozadań przed przejściem dalej, mikrozadanie, które planuje więcej, może zatrzymać wszystko inne. Przetestowaliśmy to na 100 000 połączonych mikrozadań:

let count = 0;
let timerFired = false;
setTimeout(() => { timerFired = true; }, 0);

function spin() {
  count++;
  if (count < 100000) queueMicrotask(spin);
  else console.log("timer fired during microtasks?", timerFired);
}
queueMicrotask(spin);

// timer fired during microtasks? false

Licznik czasu nie mógł działać, dopóki wszystkie nie zostały ukończone. Gdyby ten łańcuch nigdy się nie skończył, liczniki czasu nigdy by się nie uruchomiły, a w przeglądarce strona nigdy by się nie przemalowała. Zauważ, że poddanie się await w przypadku rozwiązanej obietnicy nie pomaga tutaj, ponieważ po prostu dodaje kolejne mikrozadanie. Potrzebujesz prawdziwego zadania, takiego jak minutnik, aby dać innym szansę.

Renderowanie w przeglądarkach

Przeglądarka zwykle ma szansę na malowanie pomiędzy zadaniami. To wyjaśnia typowy błąd:

spinner.hidden = false;
doHeavyWork();              // blocks the thread
spinner.hidden = true;

Pokrętło nigdy się nie pojawia, ponieważ przeglądarka nie miała możliwości renderowania między tymi liniami. Aby to naprawić, przepuść ramę przed rozpoczęciem ciężkiej pracy lub przenieś ją do pracownika. W przypadku kodu zmieniającego grafikę requestAnimationFrame uruchamia się tuż przed kolejnym malowaniem, co czyni go właściwym narzędziem do animacji.

Różnice w Node.js

Node.js ma własną pętlę zdarzeń z kilkoma fazami, w tym licznikami czasu, odpytywaniem we/wy i setImmediate. Posiada również process.nextTick, który działa we własnej kolejce. Oto, co widzieliśmy, uruchamiając je z poziomu funkcji asynchronicznej:

setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("promise"));

// promise
// nextTick
// immediate
// timeout

W wielu artykułach stwierdza się, że nextTick zawsze dotrzymuje obietnic, a licznik czasu przewyższa setImmediate. Nasz wynik pokazuje, że nie jest to takie proste. Nasz kod był już uruchomiony w ramach mikrozadania, więc kolejka obietnic była kontynuowana jako pierwsza. Wiadomo, że kolejność setTimeout i setImmediate różni się w zależności od tego, skąd są wywoływane. Dlatego nie pisz kodu, który zależy od dokładnej kolejności tych elementów. Jeśli jedna rzecz musi nastąpić po drugiej, połącz je wyraźnie.

Quiz wywiadu

Spróbuj ustalić kolejność, zanim przeczytasz odpowiedź:

console.log("a");
setTimeout(() => console.log("b"), 0);
Promise.resolve().then(() => {
  console.log("c");
  setTimeout(() => console.log("d"), 0);
  Promise.resolve().then(() => console.log("e"));
});
console.log("f");

Nasz przebieg wydrukowano a, f, c, e, b, d. Oto dlaczego:

  1. a i f są synchroniczne, więc działają jako pierwsze.
  2. Stos jest pusty, zatem uruchamiane są mikrozadania: c, następnie nowe mikrozadanie e, w tej samej rundzie.
  3. Teraz jedno zadanie: timer b, który był w kolejce jako pierwszy.
  4. Następnie kolejne zadanie: timer d, który ustawił się w kolejce podczas mikrozadania.

Typowe błędy

  • Myślenie setTimeout jest dokładne. Opóźnienie jest tylko minimalne.
  • Myślenie async oznacza inny wątek. Kod asynchroniczny nadal działa w głównym wątku pomiędzy oczekiwaniami.
  • Wykorzystywanie uśpienia do naprawiania kolejności. Oczekiwanie na rzeczywisty stan jest znacznie bardziej niezawodne, co dotyczy również niestabilnych testów.
  • Używanie forEach z await. Nie powoduje oczekiwania między elementami. Zobacz Metody tablicowe JavaScript.
  • Wykonywanie dużej pracy synchronicznej w programie obsługi serwera. Jedno żądanie może opóźnić każde inne żądanie.

Podsumowanie

Zapamiętaj podstawową zasadę: uruchamiaj stos, aż będzie pusty, uruchom wszystkie mikrozadania, następnie uruchom jedno zadanie i powtórz. Wszystko inne z tego wynika. Aby się utrwaliło, napisz własną wersję powyższego quizu, przewiduj wynik na papierze, a następnie uruchom go. Jeśli popełnisz błąd i zrozumiesz dlaczego, nauczysz się więcej niż jakikolwiek diagram.

Najczęstsze pytania

Jaka jest pętla zdarzeń w JavaScript?

Jest to mechanizm uruchamiający kolejkowane wywołania zwrotne, gdy stos wywołań jest pusty. Umożliwia jednowątkowemu JavaScriptowi obsługę timerów, danych wejściowych i odpowiedzi sieciowych bez blokowania.

Jaka jest różnica między mikrozadaniem a zadaniem?

Wszystkie mikrozadania, takie jak wywołania zwrotne obietnic, są uruchamiane natychmiast po opróżnieniu stosu. Zadania, takie jak liczniki czasu, są uruchamiane pojedynczo, a mikrozadania są usuwane po każdym.

Dlaczego setTimeout z 0 nie działa natychmiast?

Jego wywołanie zwrotne musi czekać na turę zadania. Cały kod synchroniczny i mikrozadania są uruchamiane jako pierwsze, a opóźnienie jest czasem minimalnym, a nie dokładnym.

Czy JavaScript jest jednowątkowy?

Twój główny kod JavaScript działa w jednym wątku. Przeglądarki i Node.js używają innych wątków do pracy w tle, a procesy robocze umożliwiają równoległe uruchamianie kodu.

Czy oczekiwanie blokuje pętlę zdarzeń?

Nie. Wait wstrzymuje tylko tę funkcję asynchroniczną, a w międzyczasie może działać inny kod. Długi kod synchroniczny przed lub po nim może jednak nadal blokować pętlę.

Ucz się dalej

Pracuj z Stack Quora

Potrzebujesz pomocy przy testowaniu, WordPressie lub SEO?

Pomagamy zespołom dostarczać lepsze oprogramowanie i rozwijać ich witryny. Powiedz nam, nad czym pracujesz, a my zaproponujemy jasny następny krok.

Czytaj dalej

Więcej poradników na testowanie, sztuczna inteligencja i nowoczesny rozwój

Podobał Ci się ten artykuł? Wybierz temat i przejdź bezpośrednio do naszych najnowszych tutoriali.

Sztuczna inteligencja

Wyjaśnienie halucynacji AI: dlaczego modele językowe tworzą rzeczy i jak je zmniejszyć

Wyjaśniono halucynacje AI: czym są, dlaczego powstają w modelach językowych, typowe typy, jak je zredukować za pomocą uziemień i podpowiedzi oraz pr…

Przeczytaj artykuł →
DevOps

Wyjaśnienie zmiennych środowiskowych: pliki .env, sekrety i konfiguracja wykonana prawidłowo

Zmienne środowiskowe wyjaśnione na przykładach Pythona, które przeprowadziliśmy: ich odczytywanie i ustawianie, dlaczego każda wartość jest ciągiem …

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie ograniczenia szybkości interfejsu API: algorytmy, nagłówki i obsługa błędów 429

Ograniczanie szybkości API wyjaśnione za pomocą przeprowadzonej przez nas symulacji: zasobnik tokenów, stałe okno, przesuwane okno, 429 odpowiedzi, …

Przeczytaj artykuł →
Automatyzacja testów

Wyśmiewanie w Pythonie: unittest.mock, patch i błędy, które sprawiają, że testy kłamią

Wyśmiewanie w Pythonie za pomocą unittest.mock, przetestowane: Mock i zwracana wartość, efekt uboczny, łatanie tam, gdzie używana jest nazwa, specyf…

Przeczytaj artykuł →
Testowanie oprogramowania

Wyjaśnienie zasięgu kodu: pokrycie linii i oddziału oraz co naprawdę oznacza 100%

Wyjaśnienie pokrycia kodu za pomocą prawdziwego pliku cover.py: pokrycie linii, gałęzi i warunków, przeczytanie raportu, dlaczego 100% pokrycia może…

Przeczytaj artykuł →
Bazy danych i SQL

DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

DELETE vs TRUNCATE vs DROP wyjaśnione za pomocą przetestowanego SQL: co każdy usuwa, wycofywanie, wyzwalacze, resetowanie tożsamości, prędkość i czy…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie widoków SQL: tworzenie, używanie i unikanie pułapek wraz z przykładami

Widoki SQL wyjaśnione za pomocą zapytań, które uruchomiliśmy: tworzenie widoku, wyniki na żywo, ukrywanie kolumn, wydajność, widoki z możliwością ak…

Przeczytaj artykuł →
Tworzenie oprogramowania

Interfejs TypeScript a typ: rzeczywiste różnice, testowane za pomocą kompilatora

Interfejs TypeScript a typ, sprawdzony z prawdziwym kompilatorem: co oba mogą zrobić, co tylko jeden, łączenie deklaracji, rozszerzenia a przecięcia…

Przeczytaj artykuł →
Tworzenie oprogramowania

Python *args i **kwargs wyjaśnione: elastyczne funkcje z przejrzystymi przykładami

Python *args i **kwargs wyjaśnione za pomocą uruchomionego przez nas kodu: pakowanie i rozpakowywanie, kolejność parametrów, argumenty zawierające t…

Przeczytaj artykuł →
Tworzenie oprogramowania

Funkcje Lambda w Pythonie: składnia, rzeczywiste zastosowania i kiedy ich nie używać

Funkcje lambda w Pythonie wyjaśnione za pomocą uruchomionego przez nas kodu: składnia, sortowanie za pomocą klucza, mapa i filtr, domknięcia, pułapk…

Przeczytaj artykuł →
Sztuczna inteligencja

Kim są agenci AI? Jak one działają, dzięki prostej pętli agenta, którą możesz uruchomić

Kim są agenci AI? Prosty przewodnik po pętli agenta, narzędziach, pamięci i poręczach, z małą pętlą w Pythonie, którą uruchomiliśmy, prawdziwymi zag…

Przeczytaj artykuł →
DevOps

Monitorowanie a obserwowalność: prawdziwa różnica z logami, wskaźnikami i śladami

Wyjaśnienie monitorowania a obserwowalności: znane i nieznane awarie, dzienniki, metryki i ślady, opis incydentu przy kasie, złote sygnały, OpenTele…

Przeczytaj artykuł →
DevOps

Woluminy platformy Docker a mocowania powiązań: utrwalanie danych kontenera we właściwy sposób

Wyjaśniono woluminy Dockera a montowanie powiązań: dlaczego dane kontenera znikają, nazwane woluminy, montowanie powiązań, tmpfs, przykłady tworzeni…

Przeczytaj artykuł →
Automatyzacja testów

TDD vs BDD: kluczowe różnice, jedna funkcja zbudowana w obie strony i kiedy używać każdej z nich

TDD vs BDD wyjaśnione za pomocą jednej funkcji rabatowej zbudowanej w obie strony: refaktoryzacja czerwono-zielona z uruchomionym przez nas kodem, s…

Przeczytaj artykuł →
Testowanie oprogramowania

Testowanie akceptacyjne użytkownika (UAT): proces, lista kontrolna i rzeczywiste przykłady

Wyjaśniono testy akceptacyjne użytkownika: kto je przeprowadza, czym różni się od kontroli jakości, siedmioetapowy proces, szablon przypadku testowe…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie wartości SQL NULL: IS NULL, COALESCE, NULLIF i pułapki, których należy unikać

Wartości SQL NULL wyjaśnione za pomocą zapytań, które wykonaliśmy: logika trójwartościowa, IS NULL, COALESCE, NULLIF, w jaki sposób agregacje, łącze…

Przeczytaj artykuł →
Bazy danych i SQL

Instrukcja SQL CASE WHEN: składnia, rzeczywiste przykłady i typowe błędy

SQL CASE WHEN wyjaśnione za pomocą zapytań, które uruchomiliśmy: proste i przeszukiwane formularze, kolejność warunków, elementy przestawne z SUM, s…

Przeczytaj artykuł →
Tworzenie oprogramowania

Co to jest JWT? Tokeny internetowe JSON wyjaśnione na przykładzie działania

Co to jest JWT? Wyjaśniono tokeny sieciowe JSON: trzy części, token zbudowany i zmodyfikowany w uruchomionym przez nas kodzie, JWT a sesje, pamięć m…

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie pętli zdarzeń JavaScript: stos wywołań, mikrozadania i liczniki czasu z przykładami

Pętla zdarzeń JavaScript wyjaśniona za pomocą uruchomionego przez nas kodu: stos wywołań, kolejki zadań i mikrozadań, dlaczego setTimeout 0 nie jest…

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie generatorów Pythona i wydajności: oszczędzaj pamięć dzięki prawdziwym przykładom

Generatory Pythona i wydajność wyjaśnione za pomocą uruchomionego przez nas kodu: sposób wstrzymywania i wznawiania, mierzone oszczędności pamięci, …

Przeczytaj artykuł →
Sztuczna inteligencja

Czym są osady? Wyjaśnienie wektorów i podobieństwa cosinusa

Czym są osadzania? Prosty przewodnik po wektorach, podobieństwie cosinusów i wyszukiwaniu semantycznym, z małym przykładem, który przeprowadziliśmy,…

Przeczytaj artykuł →
DevOps

Wdrożenie niebiesko-zielone a kanaryjskie: różnice, kompromisy i sposób wyboru

Wyjaśniono wdrożenie Blue-Green vs Canary: sposób działania każdego z nich, koszty, ryzyko i wycofywanie zmian, przetestowane przez nas stabilne łąc…

Przeczytaj artykuł →
Automatyzacja testów

Niestabilne testy: co je powoduje i jak je naprawić na dobre

Niestabilne testy wyjaśnione w przeprowadzonych przez nas demonstracjach: główne przyczyny, sposób potwierdzenia i zdiagnozowania jednej z nich, odp…

Przeczytaj artykuł →
Testowanie oprogramowania

Load Testing vs Stress Testing: Differences, Metrics and k6 Examples

Wyjaśniono testy obciążenia i testy warunków skrajnych: co dowodzi każdy z nich, testy szczytowe i nasiąkania, istotne metryki, dlaczego średnie wpr…

Przeczytaj artykuł →
Testowanie oprogramowania

Przypadek testowy a scenariusz testowy: kluczowe różnice, przykłady i kiedy stosować każdy z nich

Wyjaśnienie przypadków testowych i scenariuszy testowych: jasne definicje, tabela obok siebie, jedna funkcja resetowania hasła zaczerpnięta ze scena…

Przeczytaj artykuł →
Bazy danych i SQL

Optymalizacja zapytań SQL: czytaj plany wykonania i napraw powolne zapytania z synchronizacją

Optymalizacja zapytań SQL przetestowana na milionie wierszy: przeczytaj plany wykonania, dodaj odpowiednie indeksy, napraw filtry niesargowalne, uży…

Przeczytaj artykuł →
Bazy danych i SQL

SQL UNION vs UNION ALL: różnice, przykłady i testowana wydajność

SQL UNION vs UNION ALL wyjaśnione na podstawie zapytań, które uruchomiliśmy: duplikaty, obie reguły są zgodne, prawdziwy błąd danych, zmierzona wyda…

Przeczytaj artykuł →
Tworzenie oprogramowania

Samouczek API pobierania JavaScript: GET, POST, obsługa błędów i limity czasu

Samouczek JavaScript Fetch API testowany na serwerze lokalnym: GET i POST, dlaczego 404 nie rzuca, pomocnik wielokrotnego użytku, ciągi zapytań, prz…

Przeczytaj artykuł →
Tworzenie oprogramowania

Obsługa plików w Pythonie: odczyt, zapis, CSV, JSON i pathlib z przykładami

Obsługa plików w Pythonie wyjaśniona za pomocą uruchomionego przez nas kodu: tryby otwarte, czytanie dużych plików, CSV, JSON, pathlib, pliki binarn…

Przeczytaj artykuł →
Tworzenie oprogramowania

Klasy i obiekty Pythona: samouczek OOP z prawdziwymi przykładami

Klasy i obiekty Pythona objaśnione za pomocą uruchomionego przez nas kodu: __init__, metody, atrybuty klas i instancji, dziedziczenie, właściwości, …

Przeczytaj artykuł →
Sztuczna inteligencja

Co to jest model dużego języka? Jak działają LLM, wyjaśnione bez szumu

Co to jest model dużego języka? LLM wyjaśnione prostym językiem: tokeny, osadzanie, uwaga, szkolenie, temperatura i okna kontekstowe, mała demonstra…

Przeczytaj artykuł →
DevOps

Polecenia systemu Linux dla początkujących: niezbędny przewodnik po terminalu z przykładami

Polecenia systemu Linux dla początkujących, pogrupowane według zadań: nawigacja, pliki, przeglądanie logów, grep, potoki, uprawnienia, procesy i arc…

Przeczytaj artykuł →
Automatyzacja testów

Selenium kontra dramaturg: kluczowe różnice, porównanie kodu i wybór

Porównanie Selenium i Playwright: architektura, oczekiwanie, obsługa przeglądarki i języka, debugowanie, ten sam test w obu narzędziach, porady doty…

Przeczytaj artykuł →
Testowanie oprogramowania

Partycjonowanie równoważne: technika projektowania testów wyjaśniona na praktycznych przykładach

Wyjaśniono podział równoważny: jak znaleźć prawidłowe i nieprawidłowe partycje, sprawdzone przykłady dla grup wiekowych, hasła i kupony, przeprowadz…

Przeczytaj artykuł →
Testowanie oprogramowania

Ważność a priorytet w testowaniu oprogramowania: różnice, macierz i rzeczywiste przykłady

Wyjaśniono ważność a priorytet w testowaniu oprogramowania: jasne definicje, czterokierunkowa macierz z przykładami, skale poziomów, kto ustawia każ…

Przeczytaj artykuł →
Bazy danych i SQL

Samouczek dotyczący podzapytań SQL: typy, skorelowane podzapytania i ISTNIEJĄ z przykładami

Samouczek dotyczący podzapytań SQL z zapytaniami, które wykonaliśmy: podzapytania skalarne, IN, FROM i SELECT, podzapytania skorelowane, EXISTS, puł…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie transakcji SQL i ACID: COMMIT, ROLLBACK i poziomy izolacji

Transakcje SQL i ACID wyjaśnione za pomocą wykonanego przez nas przelewu bankowego: COMMIT, ROLLBACK, punkty zapisu, blokady, poziomy izolacji, brud…

Przeczytaj artykuł →
Tworzenie oprogramowania

Git merge vs rebase: różnice, przykłady i kiedy czego używać

Git merge vs rebase wyjaśnione na prawdziwym wyniku logu, z tabelą porównawczą, złotą zasadą rebase i bezpiecznym procesem pracy zespołu.

Przeczytaj artykuł →
Tworzenie oprogramowania

Python list comprehension: składnia, przykłady i kiedy jej unikać

Python list comprehension wyjaśnione: składnia, filtrowanie, if-else, zagnieżdżone pętle, zmierzone czasy i sytuacje, w których zwykła pętla for jes…

Przeczytaj artykuł →
Bazy danych i SQL

SQL JOIN – wyjaśnienie z przykładami (Inner, Left, Right, Full)

Zrozum złączenia SQL krok po kroku na przykładowych tabelach i zapytaniach: INNER, LEFT, RIGHT, FULL, CROSS i SELF, plus typowe błędy i wskazówki wy…

Przeczytaj artykuł →