wzorce projektowe JavaScript: wzorzec obserwatora

w języku JavaScript często pojawia się problem. Potrzebujesz sposobu na aktualizację części strony w odpowiedzi na określone zdarzenia, z dostarczonymi przez nie danymi. Na przykład dane wejściowe użytkownika, które następnie projektujesz w jednym lub wielu komponentach. Prowadzi to do wielu push-and-pull w kodzie, aby wszystko zsynchronizować.

tutaj może pomóc wzorzec projektowy observer — umożliwia powiązanie danych od jednego do wielu elementów. To jednokierunkowe powiązanie danych może być sterowane zdarzeniami. Dzięki temu wzorcowi możesz zbudować kod wielokrotnego użytku, który rozwiąże twoje specyficzne potrzeby.

w tym artykule chciałbym zbadać wzór projektu obserwatora. Pomoże Ci to rozwiązać wspólny problem, który widzisz w skryptach po stronie klienta. Jest to powiązanie danych jeden do wielu, jednokierunkowe i oparte na zdarzeniach. Jest to problem, który pojawia się często, gdy masz wiele elementów, które muszą być zsynchronizowane.

użyję ECMAScript 6 do zilustrowania wzorca. Tak, będą klasy, funkcje strzałek i stałe. Zachęcamy do samodzielnego odkrywania tych tematów, Jeśli jeszcze ich nie znasz. Użyję części ES6, które wprowadzają tylko cukier składniowy, więc w razie potrzeby jest przenośny z ES5.

i użyję Test-Driven-Development (TDD) do pracy nad wzorcem. W ten sposób Masz sposób wiedząc, jak każdy komponent jest przydatny.

nowe funkcje językowe w ES6 sprawiają, że kod jest zwięzły. Więc zaczynajmy.

Obserwator zdarzeń

widok wzorca na wysokim poziomie wygląda następująco:

EventObserver│ ├── subscribe: adds new observable events│ ├── unsubscribe: removes observable events|└── broadcast: executes all events with bound data

po uformowaniu wzoru obserwatora dodam liczbę słów, która go używa. Komponent word count weźmie tego obserwatora i połączy to wszystko razem.

aby zainicjować EventObserver do:

class EventObserver { constructor() { this.observers = ; }}

zacznij od pustej listy obserwowanych zdarzeń i zrób to dla każdej nowej instancji. Od teraz dodajmy więcej metod wewnątrz EventObserver, aby ułożyć wzór projektowy.

metoda Subskrybuj

aby dodać nowe wydarzenia do:

subscribe(fn) { this.observers.push(fn);}

chwyć listę obserwowanych zdarzeń i wypchnij nowy element do tablicy. Lista zdarzeń jest listą funkcji zwrotnych.

jednym ze sposobów testowania tej metody w prostym JavaScript jest następujący:

// Arrangeconst observer = new EventObserver();const fn = () => {};// Actobserver.subscribe(fn);// Assertassert.strictEqual(observer.observers.length, 1);

używam asercji Node do testowania tego komponentu w Node. Te same twierdzenia istnieją również jako twierdzenia Chai.

Uwaga Lista obserwowanych zdarzeń składa się z skromnych wywołań zwrotnych. Następnie sprawdzamy długość listy i stwierdzamy, że wywołanie zwrotne jest na liście.

metoda anulowania subskrypcji

, aby usunąć zdarzenia do:

unsubscribe(fn) { this.observers = this.observers.filter((subscriber) => subscriber !== fn);}

Filtruj z listy wszystko, co pasuje do funkcji zwrotnej. Jeśli nie ma dopasowania, oddzwonienie zostaje na liście. Filtr zwraca nową listę i przypisuje listę obserwatorów.

aby przetestować tę fajną metodę, zrób:

// Arrangeconst observer = new EventObserver();const fn = () => {};observer.subscribe(fn);// Actobserver.unsubscribe(fn);// Assertassert.strictEqual(observer.observers.length, 0);

wywołanie zwrotne musi pasować do tej samej funkcji, która jest na liście. Jeśli istnieje dopasowanie, metoda unsubscribe usuwa go z listy. Uwaga test używa referencji funkcji, aby ją dodać i usunąć.

Metoda transmisji

aby wywołać wszystkie zdarzenia do:

broadcast(data) { this.observers.forEach((subscriber) => subscriber(data));}

to iteracje przez listę obserwowanych zdarzeń i wykonuje wszystkie wywołania zwrotne. Dzięki temu uzyskujesz niezbędny związek jeden do wielu z subskrybowanymi wydarzeniami. Przekazujesz parametr data, który powoduje powiązanie danych zwrotnych.

ES6 sprawia, że kod jest bardziej efektywny dzięki funkcji strzałki. Zwróć uwagę na funkcję (subscriber) => subscriber(data), która wykonuje większość pracy. Ta funkcja strzałki jednowierszowej korzysta z tej krótkiej składni ES6. Jest to zdecydowana poprawa w języku programowania JavaScript.

aby przetestować tę metodę transmisji, wykonaj:

// Arrangeconst observer = new EventObserver();let subscriberHasBeenCalled = false;const fn = (data) => subscriberHasBeenCalled = data;observer.subscribe(fn);// Actobserver.broadcast(true);// Assertassert(subscriberHasBeenCalled);

użyj let zamiast const, abyśmy mogli zmienić wartość zmiennej. To sprawia, że zmienna jest zmienna, co pozwala mi na zmianę jej wartości wewnątrz wywołania zwrotnego. Użycie let w kodzie wysyła sygnał do innych programistów, że zmienna zmienia się w pewnym momencie. To dodaje czytelność i przejrzystość kodu JavaScript.

ten test daje mi pewność, że obserwator działa zgodnie z oczekiwaniami. W TDD chodzi o budowanie kodu wielokrotnego użytku w prostym JavaScript. Istnieją korzyści z pisania testowalnego kodu w prostym JavaScript. Przetestuj wszystko i zachowaj to, co jest dobre dla ponownego użycia kodu.

dzięki temu udoskonaliliśmy EventObserver. Pytanie brzmi, co można z tego zbudować?

wzorzec obserwatora w akcji: Demo liczby słów na blogu

w przypadku demo czas umieścić post na blogu, w którym utrzymuje liczbę słów dla Ciebie. Każde naciśnięcie klawisza wprowadzone jako wejście zostanie zsynchronizowane przez wzorzec projektowy obserwatora. Pomyśl o tym jak o swobodnym wprowadzaniu tekstu, w którym każde zdarzenie wywołuje aktualizację do miejsca, w którym jest ona potrzebna.

aby uzyskać liczbę słów z swobodnego wprowadzania tekstu, można zrobić:

const getWordCount = (text) => text ? text.trim().split(/\s+/).length : 0;

zrobione! Wiele się dzieje w tej pozornie prostej, czystej funkcji, więc co powiesz na skromny test jednostkowy? W ten sposób jest jasne, co zamierzałem zrobić:

// Arrangeconst blogPost = 'This is a blog \n\n post with a word count. ';// Actconst count = getWordCount(blogPost);// Assertassert.strictEqual(count, 9);

zwróć uwagę na nieco zwariowany ciąg wejściowy wewnątrz blogPost. Chcę, aby ta funkcja objęła jak najwięcej przypadków skrajnych, jak to możliwe. Tak długo, jak daje mi to odpowiednią liczbę słów, zmierzamy właściwie we właściwym kierunku.

na marginesie, jest to prawdziwa moc TDD. Można iteracji na tej implementacji i obejmować jak najwięcej przypadków użycia, Jak to możliwe. Test jednostkowy mówi ci, jak to ma się zachowywać. Jeśli zachowanie ma wadę, z jakiegokolwiek powodu łatwo jest je iterować i dostosować. Z testem jest wystarczająco dużo dowodów, aby każda inna osoba mogła wprowadzić zmiany.

czas podłączyć te komponenty wielokrotnego użytku do drzewa DOM. Jest to część, w której możesz używać zwykłego JavaScript i spawać go bezpośrednio w przeglądarce.

sposobem na to byłoby posiadanie następującego kodu HTML na stronie:

<textarea placeholder="Enter your blog post..." class="blogPost"></textarea>

Followed up by this JavaScript:

const wordCountElement = document.createElement('p');wordCountElement.className = 'wordCount';wordCountElement.innerHTML = 'Word Count: <strong>0</strong>';document.body.appendChild(wordCountElement);const blogObserver = new EventObserver();blogObserver.subscribe((text) => { const blogCount = document.getElementById('blogWordCount'); blogCount.textContent = getWordCount(text);});const blogPost = document.getElementById('blogPost');blogPost.addEventListener('keyup', () => blogObserver.broadcast(blogPost.value));

weź cały kod wielokrotnego użytku i umieść wzór projektu obserwatora. To będzie śledzić zmiany w obszarze tekstowym i daje liczbę słów tuż pod nim. Używam body.appendChild() w DOM API, aby dodać ten nowy element. Następnie dołączenie słuchaczy wydarzenia, aby ożywić go.

Uwaga dzięki funkcjom strzałek możliwe jest podłączanie zdarzeń jednoliniowych. W rzeczywistości dzięki temu możesz transmitować zmiany związane z wydarzeniami dla wszystkich subskrybentów. () => blogObserver.broadcast() wykonuje tu większość pracy. Przekazuje nawet najnowsze zmiany w obszarze tekstowym bezpośrednio do funkcji zwrotnej. Tak, skrypty po stronie klienta są super fajne.

żadne demo nie jest kompletne bez takiego, którego można dotknąć i dostosować, poniżej znajduje się CodePen:

Zobacz Pióro wzór obserwatora przez SitePoint (@SitePoint) na CodePen.

teraz nie nazwałbym tej funkcji kompletną. Jest to jedynie punkt wyjścia wzorca projektowego obserwatora. Pytanie w mojej głowie brzmi, jak daleko jesteś w stanie się posunąć?

patrząc w przyszłość

to od Ciebie zależy, czy weźmiesz ten pomysł jeszcze dalej. Istnieje wiele sposobów wykorzystania wzorca projektowego obserwatora do tworzenia nowych funkcji.

możesz wzbogacić demo o:

  • kolejny komponent, który zlicza liczbę akapitów
  • kolejny komponent, który pokazuje podgląd wprowadzonego tekstu
  • Ulepsz PODGLĄD Dzięki obsłudze znaczników, na przykład

to tylko kilka pomysłów, które możesz zrobić, aby zagłębić się w to głębiej. Powyższe ulepszenia będą stanowić wyzwanie dla programistów.

wniosek

wzór projektu obserwatora może pomóc w rozwiązywaniu rzeczywistych problemów w JavaScript. Rozwiązuje to odwieczny problem utrzymywania kilku elementów zsynchronizowanych z tymi samymi danymi. Jak to często bywa, gdy przeglądarka uruchamia określone zdarzenia. Jestem pewien, że większość z was już natknęła się na taki problem i biegła w kierunku narzędzi i zależności od innych firm.

ten wzór projektowy pozwala Ci iść tak daleko, jak twoja wyobraźnia jest gotowa. W programowaniu abstrakcja rozwiązania do wzorca i tworzenie kodu wielokrotnego użytku. Nie ma ograniczeń co do tego, jak daleko cię to zaprowadzi.

mam nadzieję, że widzisz, ile, przy odrobinie dyscypliny i wysiłku, możesz zrobić w prostym JavaScript. Nowe funkcje w języku, takie jak ES6, pomagają napisać zwięzły kod, który jest wielokrotnego użytku.

ten artykuł został zweryfikowany przez Giulio Mainardi. Dziękujemy wszystkim recenzentom SitePoint za to, że treści SitePoint są najlepsze!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.