vzory návrhu JavaScriptu: vzor pozorovatele

v JavaScriptu se často objevuje problém. Potřebujete způsob, jak aktualizovat části stránky v reakci na určité události, s údaji, které poskytují. Řekněme například Uživatelský vstup, který pak promítnete do jedné nebo mnoha komponent. To vede k hodně push-and-pull v kódu, aby vše v synchronizaci.

zde může pomoci vzor návrhu pozorovatele-umožňuje vazbu dat mezi jednotlivými prvky. Tato jednosměrná vazba dat může být řízena událostmi. Pomocí tohoto vzoru můžete vytvořit opakovaně použitelný kód, který řeší vaše konkrétní potřeby.

v tomto článku bych chtěl prozkoumat vzor návrhu pozorovatele. Pomůže vám vyřešit běžný problém, který vidíte v skriptování na straně klienta. To je one-to-many, jednosměrný, a event-driven data binding. Je to problém, který se objevuje často, když máte mnoho prvků, které musí být synchronizovány.

pro ilustraci vzoru použiji ECMAScript 6. Ano, budou existovat třídy, funkce šipek a konstanty. Pokud ještě nejste obeznámeni, můžete tato témata prozkoumat sami. Budu používat části ES6, které zavádějí pouze syntaktický cukr, takže je v případě potřeby Přenosný s ES5.

a budu používat Test-Driven-Development (TDD) pro práci na vzoru. Tímto způsobem máte způsob, jak vědět, jak je každá součást užitečná.

nové jazykové funkce v ES6 vytvářejí nějaký stručný kód. Takže začneme.

pozorovatel události

pohled na vzor na vysoké úrovni vypadá takto:

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

poté, co jsem zhmotnit vzor pozorovatele přidám počet slov, který ji používá. Komponenta počet slov vezme tohoto pozorovatele a spojí to všechno dohromady.

pro inicializaci EventObserver do:

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

začněte prázdným seznamem pozorovaných událostí a proveďte to pro každou novou instanci. Od této chvíle přidejme další metody uvnitř EventObserver, abychom vytvořili návrhový vzor.

metoda odběru

pro přidání nových událostí:

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

uchopte seznam pozorovaných událostí a zatlačte novou položku do pole. Seznam událostí je seznam funkcí zpětného volání.

jeden způsob, jak otestovat tuto metodu v prostém JavaScriptu, je následující:

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

používám tvrzení uzlů k testování této komponenty v uzlu. Existují přesně stejná tvrzení jako tvrzení Chai.

Poznámka seznam pozorovaných událostí se skládá ze skromných zpětných volání. Poté zkontrolujeme délku seznamu a tvrdíme, že zpětné volání je v seznamu.

metoda odhlášení

k odstranění událostí:

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

odfiltrujte ze seznamu, co odpovídá funkci zpětného volání. Pokud není shoda, zpětné volání zůstane na seznamu. Filtr vrací nový seznam a znovu přiřadí seznam pozorovatelů.

Chcete-li otestovat tuto pěknou metodu, proveďte:

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

zpětné volání musí odpovídat stejné funkci, která je v seznamu. Pokud existuje shoda, metoda odhlášení ji odstraní ze seznamu. Poznámka: test používá odkaz na funkci k přidání a odebrání.

metoda vysílání

pro volání všech událostí:

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

to iteruje prostřednictvím seznamu pozorovaných událostí a provede všechna zpětná volání. S tím, získáte potřebný individuální vztah k předplatným událostem. Předáte parametr data, díky kterému jsou data zpětného volání vázána.

ES6 zefektivňuje kód pomocí funkce šipky. Všimněte si funkce (subscriber) => subscriber(data), která provádí většinu práce. Tato funkce s jednou linerovou šipkou těží z této krátké syntaxe ES6. Jedná se o jednoznačné zlepšení v programovacím jazyce JavaScript.

Chcete-li otestovat tuto metodu vysílání, proveďte:

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

použijte let místo const , abychom mohli změnit hodnotu proměnné. Díky tomu je proměnná proměnná, což mi umožňuje znovu přiřadit její hodnotu uvnitř zpětného volání. Použití let ve vašem kódu vyšle signál kolegům programátorům, že proměnná se v určitém okamžiku mění. To přidává čitelnost a jasnost kódu JavaScript.

tento test mi dává jistotu nezbytnou k zajištění toho, aby pozorovatel pracoval tak, jak očekávám. S TDD je to všechno o vytváření opakovaně použitelného kódu v prostém JavaScriptu. Psaní testovatelného kódu v prostém JavaScriptu má výhody. Otestujte vše a zachovejte to, co je dobré pro opětovné použití kódu.

tímto jsme vytvořili EventObserver. Otázkou je, co s tím můžete postavit?

The Observer Pattern in Action: a Blog Word Count Demo

pro demo je čas zavést blogový příspěvek, kde udržuje počet slov pro vás. Každé stisknutí klávesy, které zadáte jako vstup, se synchronizuje podle vzoru návrhu pozorovatele. Přemýšlejte o tom jako o volném zadávání textu, kde každá událost spustí aktualizaci tam, kam ji potřebujete.

Chcete-li získat počet slov z volného zadávání textu, můžete to udělat:

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

Hotovo! V této zdánlivě jednoduché čisté funkci se toho hodně děje, tak co takhle skromný test jednotky? Tímto způsobem je jasné, co jsem chtěl udělat:

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

Všimněte si poněkud nezvyklého vstupního řetězce uvnitř blogPost. Mám v úmyslu, aby tato funkce pokrývala co nejvíce okrajových případů. Pokud mi to dá správný počet slov, jdeme ve skutečnosti správným směrem.

jako vedlejší poznámka je to skutečná síla TDD. Jeden může iterovat na této implementaci a pokrýt co nejvíce případů použití, jak je to možné. Test jednotky vám řekne, jak očekávám, že se to bude chovat. Pokud má chování chybu, z jakéhokoli důvodu je snadné ji iterovat a vyladit. S testem, zbývá dostatek důkazů pro jakoukoli jinou osobu, aby provedla změny.

je čas zapojit tyto opakovaně použitelné komponenty do DOM. To je část, kde se dostanete ovládat prostý JavaScript a svařit ji přímo do prohlížeče.

způsob, jak to udělat, by bylo mít následující HTML na stránce:

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

následuje tento 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));

Vezměte všechny své opakovaně použitelný kód a zavést pozorovatel design vzor. To bude sledovat změny v textové oblasti a dá vám počet slov přímo pod ním. Používám body.appendChild() v DOM API přidat tento nový prvek. Poté připojte posluchače události k životu.

Poznámka S funkcí šipky je možné zapojit jednořádkové události. Ve skutečnosti s tím vysíláte změny založené na událostech všem předplatitelům. () => blogObserver.broadcast() dělá většinu práce zde. Dokonce předává nejnovější změny v textové oblasti přímo do funkce zpětného volání. Ano, skriptování na straně klienta je super cool.

žádné demo není kompletní bez jednoho můžete dotknout a vyladit, níže je CodePen:

podívejte se na pero pozorovatel vzor SitePoint (@SitePoint) na CodePen.

nyní bych tuto funkci nenazval úplnou. Je to jen výchozí bod vzoru pozorovatele. Otázkou v mé mysli je, jak daleko jste ochotni jít?

při pohledu do budoucna

je na vás, abyste tuto myšlenku posunuli ještě dále. Existuje mnoho způsobů, jak můžete použít vzor návrhu pozorovatele k vytváření nových funkcí.

demo můžete vylepšit pomocí:

  • další komponenta, která počítá počet odstavců
  • další komponenta, která zobrazuje náhled zadaného textu
  • Vylepšete náhled pomocí podpory markdown, například

Toto je jen několik nápadů, které můžete udělat, abyste se do toho ponořili hlouběji. Výše uvedená vylepšení budou výzvou pro vaše programovací kotlety.

závěr

vzor návrhu pozorovatele vám může pomoci vyřešit problémy v reálném světě v JavaScriptu. To řeší trvalý problém udržování spoustu prvků synchronizovaných se stejnými daty. Jak často se stává, když prohlížeč spustí konkrétní události. Jsem si jistý, že většina z vás už narazila na takový problém a narazila na Nástroje a závislosti třetích stran.

tento designový vzor vás vybaví, abyste šli tak daleko, jak je vaše představivost ochotna jít. Při programování abstrahujete řešení do vzoru a vytvoříte opakovaně použitelný kód. Neexistuje žádný limit, jak daleko vás to zavede.

doufám, že uvidíte, jak moc, s trochou disciplíny a úsilí, můžete udělat v prostém JavaScriptu. Nové funkce v jazyce, jako je ES6, vám pomohou napsat nějaký stručný kód, který je opakovaně použitelný.

tento článek byl recenzován Giulio Mainardi. Díky všem recenzentům SitePoint za to, že obsah SitePoint je nejlepší, co může být!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.