Visszahívásokat hajtottam végre, vagy csak a programom más funkcióiból indítottam be a funkciókat, hogy a feladatok elvégzése után történjenek a dolgok. Amikor valami befejeződik, közvetlenül elindítom a függvényt:
var ground = "clean"; function shovelSnow(){ console.log("Cleaning Snow"); ground = "clean"; } function makeItSnow(){ console.log("It"s snowing"); ground = "snowy"; shovelSnow(); }
De “ve” a programozás számos különféle stratégiájáról olvashat, és az egyik, amelyet megértek erőteljesnek, de még nem gyakoroltam, eseményalapú (azt hiszem, egy módszert, amiről olvastam, “pub-sub” -nak hívták) :
var ground = "clean"; function shovelSnow(){ console.log("Cleaning Snow"); ground = "clean"; } function makeItSnow(){ console.log("It"s snowing"); ground = "snowy"; $(document).trigger("snow"); } $(document).bind("snow", shovelSnow);
Szeretném megérteni az esemény objektív erősségeit és gyengeségeit programozás, csak az összes funkció meghívása más funkciókból. Mely programozási helyzetekben van értelme használni az eseményalapú programozást?
Megjegyzések
Válasz
Egy esemény a közelmúlt eseményét leíró értesítés.
Az eseményvezérelt rendszer tipikus megvalósítása esemény diszpécser és kezelő funkciókat használ (vagy előfizetők ). A diszpécser biztosítja az API-t az eseménykezelőkig történő vezetékes kezelőkhöz (jQuery “s bind
) és módszert egy esemény közzétételéhez előfizetőinek (trigger
in jQuery). Amikor IO vagy UI eseményekről beszélsz, ott általában van egy esemény hurok is, amely észleli az új eseményeket, például az egérkattintásokat, és továbbítja azokat a diszpécsernek. A JS-landot, a diszpécsert és az eseményhurkot a böngésző biztosítja.
A felhasználóval közvetlenül interakcióban lévő kódra – reagálva a billentyűleütésekre és kattintásokra – eseményvezérelt programozás (vagy annak egy változata, például funkcionális reaktív programozás ) szinte elkerülhetetlen. Önnek, a programozónak fogalma sincs arról, hogy a felhasználó mikor és hol fog kattintani, ezért a GUI keretrendszerhez tartozik vagy böngésző segítségével észlelheti a felhasználó műveletét az eseményhurokban és értesítheti a kódot. Ezt a típusú infrastruktúrát hálózati alkalmazásokban is használják (vö. NodeJS).
Példája, ahol eseményt emel > yo-ban Az ur code nek ahelyett, hogy közvetlenül meghívnánk a függvényt, van még néhány érdekes kompromisszum, amelyeket az alábbiakban tárgyalok. A fő különbség az, hogy egy esemény közzétevője (makeItSnow
) nem határozza meg a hívás vevőjét; hogy máshol van bekötve (a példában a bind
hívásban). Ezt hívják tűz-felejts nek: makeItSnow
bejelenti a világnak, hogy havazik, de nem érdekli, hogy ki hallgatja, mi történik ezután, vagy mikor történik meg – egyszerűen továbbítja az üzenetet és leporolja a kezét.
Tehát az eseményvezérelt megközelítés leválasztja az üzenet feladóját a vevőről. Ennek egyik előnye, hogy egy eseménynek több kezelője lehet. Megköthet egy gritRoads
függvényt a hóeseményéhez anélkül, hogy befolyásolná a meglévő shovelSnow
kezelőt. Rugalmas az alkalmazás bekötésének módja; Egy viselkedés kikapcsolásához egyszerűen el kell távolítania a bind
hívást, ahelyett, hogy a kódot át kellene keresnie a viselkedés összes példányának megtalálásához.
A Az eseményvezérelt programozás az, hogy ad valahol átfogó kérdéseket felvetni. Az eseménydiszpécser az közvetítő szerepet játszik, és egyes könyvtárak (például a Brighter ) felhasználják egy csővezeték, amellyel könnyedén beillesztheti az általános követelményeket, például a naplózást vagy a szolgáltatás minőségét.
Teljes körű közzététel: A Brighter fejlesztése a Huddle-nál történik, ahol dolgozom.
Az esemény feladójának a vevőtől való leválasztásának harmadik előnye, hogy rugalmasságot biztosít amikor az esemény kezeléséhez. Feldolgozhatja az egyes eseménytípusokat a saját szálán (ha az esemény diszpécsere támogatja), vagy felveheti a felvetett eseményeket egy üzenetközvetítőre, például RabbitMQ kezelje őket aszinkron eljárással, vagy akár egész éjjel ömlesztve dolgozza fel őket. Az esemény vevője lehet külön folyamatban vagy külön gépen. Ehhez nem kell megváltoztatnia a kódot, amely az eseményt felveti! Ez a nagy ötlet a “mikroszolgáltatás” architektúrák mögött: az autonóm szolgáltatások események segítségével kommunikálnak, az alkalmazás gerinceként az üzenetküldő köztes szoftverek találhatók.
Az eseményvezérelt stílus egy egészen más példája a tartományvezérelt tervezés, ahol domainesemények az aggregátumok elkülönítésének elősegítésére szolgálnak. Vegyünk például egy online áruházat, amely termékeket ajánl a vásárlási előzmények alapján. A Customer
vásárlási előzményeit frissíteni kell, amikor egy ShoppingCart
-et fizetnek. A ShoppingCart
aggregátum egy CheckoutCompleted
esemény felemelésével értesítheti a Customer
-t; a Customer
külön tranzakcióban frissülne az eseményre válaszul.
Ennek az eseményvezérelt modellnek a fő hátránya az iránytalanság. Most nehezebb megtalálni az eseményt kezelő kódot, mert nem csak az IDE segítségével navigálhat hozzá; ki kell derítenie, hová van kötve az esemény a konfigurációban, és remélnie kell, hogy megtalálta az összes kezelőt. Egyszerre több dolgot kell a fejében tartania. Ebben segíthetnek a kódstílus-konvenciók (például ha az összes hívást a bind
címre helyezzük egy fájlba). A józan eszed érdekében fontos, hogy csak egy rendezvény diszpécsert használj és következetesen használd.
További hátrány, hogy az eseményeket nehéz refaktorozni. Ha módosítania kell egy esemény formátumát, akkor az összes vevőt is meg kell változtatnia. Ez súlyosbodik, ha egy esemény előfizetői különböző gépeken tartózkodnak, mert most szinkronizálnia kell a szoftverkiadásokat!
Bizonyos körülmények között a teljesítmény okozhat gondot. Üzenet feldolgozása során a diszpécsernek:
- meg kell keresnie a megfelelő kezelőket valamilyen adatstruktúrában.
- Építenie kell egy üzenetkezelő folyamatot minden kezelőhöz. Ez egy csomó memória-allokációt tartalmazhat.
- Dinamikusan hívja meg a kezelőket (esetleg reflexióval, ha a nyelv megköveteli).
Ez minden bizonnyal lassabb, mint egy normál függvény hívás, amely csak egy új keret kitolását jelenti a veremre. Azonban az eseményvezérelt architektúra által nyújtott rugalmasság sokkal könnyebbé teszi a lassú kód elkülönítését és optimalizálását. A munka elküldése aszinkron processzorhoz itt nagy győzelem, mivel lehetővé teszi az igények azonnali kiszolgálását, miközben a kemény munkával a háttérben foglalkozunk. Mindenesetre, ha kölcsönhatásba lép a DB-vel, vagy rajzol a képernyőn megjelenő tartalmakat, akkor az IO költségei teljesen elszámolják az üzenet feldolgozásának költségeit. Ez elkerülheti az idő előtti optimalizálást.
Összefoglalva: az események remek módja a lazán összekapcsolt szoftverek felépítésének, de nem költségmentesek. Hiba lenne például az alkalmazás minden függvényhívását eseményre cserélni. Az események segítségével értelmes építészeti felosztásokat végezhet.
Megjegyzések
- Ez a válasz ugyanazt mondja, mint az 5377 ‘ s válasz, amelyet helyesnek választottam; ‘ Módosítom a választásomat, hogy ezt jelöljem meg, mert tovább bővül.
- A sebesség jelentős hátránya az eseményvezérelt kódnak? Úgy tűnik, lehet, de nem tudom, hogy ‘ nem tudom.
- @ raptortech97 biztosan lehet. Ha a kódnak különösen gyorsnak kell lennie, akkor valószínűleg el szeretné kerülni az események belső hurokban történő küldését; szerencsére ilyen helyzetekben általában jól meghatározza, hogy mit kell tennie, ezért nem kell ‘ szüksége az események extra rugalmasságára (vagy publikálásra / feliratkozásra vagy megfigyelőkre, amelyek egyenértékű mechanizmusok különböző terminológia).
- Vegye figyelembe azt is, hogy vannak olyan nyelvek (pl. Erlang), amelyek a színész modell köré épülnek, ahol minden üzenet (esemény). Ebben az esetben a fordító eldöntheti, hogy az üzeneteket / eseményeket közvetlen függvényhívásként vagy kommunikációként valósítja-e meg.
- A ” teljesítményhez ” Úgy gondolom, hogy különbséget kell tennünk az egyszálas teljesítmény és a skálázhatóság között. Az üzenetek / események rosszabbak lehetnek az egyszálas teljesítmény szempontjából (de átalakíthatók függvényhívásokká, nulla többletköltség nélkül és nem rosszabbak), a méretezhetőség szempontjából pedig ‘ gyakorlatilag minden módon (pl. valószínűleg hatalmas teljesítményjavulást eredményez a modern multi-CPU és a jövőbeni ” many-CPU ” rendszereken).
Válasz
Eseményalapú programozást akkor használnak, ha a program nem ellenőrzi az általa végrehajtott események sorrendjét. Ehelyett a program folyamatát egy külső folyamat irányítja, például egy felhasználó (pl. GUI), egy másik rendszer (pl. Kliens / szerver) vagy más folyamat (pl. RPC).
Például kötegelt feldolgozó szkript tudja, mit kell tennie, ezért csak megteszi. nem eseményalapú.
Szövegszerkesztő ül ott, és várja, hogy a felhasználó elkezdjen gépelni.A kulcsnyomások olyan események, amelyek működését váltják ki a belső dokumentumpuffer frissítéséhez. A program nem tudja, hogy mit szeretne begépelni, ezért eseményvezéreltnek kell lennie.
A legtöbb GUI program eseményvezérelt, mert a felhasználói interakció köré épül. Az eseményalapú programok azonban nem korlátozódnak a grafikus felhasználói felületekre, ez egyszerűen a legismertebb példa a legtöbb ember számára. A webkiszolgálók megvárják az ügyfelek csatlakozását, és hasonló idiómát követnek. A számítógép hátterének folyamatai is reagálhatnak az eseményekre. Például egy igény szerinti víruskereső eseményeket kaphat az operációs rendszertől egy újonnan létrehozott vagy frissített fájl kapcsán, majd az adott fájlt vírusok után kutatja.
Válasz
Eseményalapú alkalmazásban az Eseményhallgatók koncepció lehetővé teszi, hogy még többet írjon Lazán összekapcsolt alkalmazások.
Például egy harmadik féltől származó modul vagy beépülő modul törölhet egy rekordot az adatbázisból, majd kiválthatja a receordDeleted
esemény, a többit pedig hagyja az esemény hallgatóinak, hogy végezzék munkájukat. Minden jól fog működni, annak ellenére, hogy a kiváltó modul azt sem tudja, hogy kik hallgatják az adott eseményt, vagy mi történjen ezután.
Válasz
Egy egyszerű hasonlat, amelyet hozzá akartam adni:
Gondoljon alkalmazásának összetevőire (vagy objektumaira), mint a Facebook barátainak nagy csoportjára.
Amikor az egyik ismerősöd el akar mondani valamit, akkor közvetlenül felhívhat, vagy közzéteheted a Facebook-falukon. Amikor közzéteszik a Facebook-on, akkor bárki láthatná és reagálhatna rá, de sokan nem teszik meg. Néha fontos dolog, hogy az embereknek valószínűleg reagálniuk kell erre, például a “Mi szülünk babát!” vagy a “So-and-so zenekar meglepetés koncertet tart a Drunkinban “Kagyló bár!”. Az utolsó esetben a többi barátnak valószínűleg reagálnia kell rá, különösen, ha érdekli őket a zenekar.
Ha a barátod titkot akar tartani közted és köztük, akkor valószínűleg nem tennék fel a Facebook-falukra, közvetlenül felhívnának és elmondanának. Készítsen egy forgatókönyvet, ahol elmondja egy tetsző lánynak, hogy szeretne találkozni vele egy étteremben randira. Ahelyett, hogy közvetlenül felhívná és megkérdezné őt, felteszed a Facebook-faladra, hogy az összes barátod láthassa. Ez működik, de ha van féltékeny voltod, akkor ezt láthatta, és megjelenhetett az étteremben, hogy tönkretegye a napodat.
Mikor gondolkodjon el erről az analógiáról. Annak eldöntése, hogy építenek-e eseményfigyelőket valamilyen megvalósítás érdekében, gondolkodjon el ezen a hasonlaton. Szüksége van-e ennek a komponensnek az üzletükre, hogy bárki láthassa őket? Vagy közvetlenül hívniuk kell valakit? óvatos.
Válasz
Ez a következő analógia segíthet Önnek u megérteni az eseményvezérelt I / O programozást úgy, hogy párhuzamot húz a várakozási sorral a doktor recepcióján.
Az I / O letiltása olyan, mintha Ön állna a sorban, a recepciós megkér egy előtted lévő srácot, hogy töltse ki az űrlapot, és ő várja, amíg befejezi. Meg kell várni a sorodra, amíg a srác elkészíti az űrlapját, ez blokkolja.
Ha az egyedülálló srác 3 percet vesz igénybe a kitöltéssel, a 10. srácnak 30 percig kell várnia. A 10. srácok várakozási idejének csökkentése érdekében megoldást jelentene a recepciósok számának növelése, ami költséges. Ez történik a hagyományos webszervereken. Ha felhasználói információt kér, a többi felhasználó későbbi kérésére várnia kell a az aktuális művelet, az adatbázisból való lekérés befejeződött. Ez megnöveli a 10. kérés “válaszidőét”, és exponenciálisan nő az n-edik felhasználó számára. Ennek elkerülése érdekében a hagyományos webszerverek minden egyes kéréshez szálat hoznak létre (egyenértékű a recepciósok számának növekedésével). , azaz lényegében minden egyes kéréshez létrehoz egy példányt a szerverről, amely költséges beleszólást jelent a CPU-ban, mivel minden kéréshez operációs rendszer-szálra lesz szükség. Az alkalmazás bővítéséhez sok számítási teljesítményt kell dobnia az alkalmazásra .
Eseményvezérelt : A “válaszidő” növelésének másik megközelítése: menjen eseményvezérelt megközelítésre, ahol a sorban lévő srácokat átadják a űrlapot, kérték, hogy töltse ki és jöjjön vissza a kitöltés után. Ezért a recepciós mindig fogadhat kérést. Pontosan ez az, amit a javascript a kezdetektől fogva csinált. A böngészőben a javascript válaszol a felhasználó kattintási eseményére, görgetésre, csúsztatásra vagy az adatbázis-lekérésre stb. objektumok, és paraméterként átadhatók más funkcióknak (visszahívásoknak), és meghívhatók egy adott feladat befejezésekor, pontosan ezt teszi a node.js a szerveren.Az eseményvezérelt programozásról és az i / o blokkolásáról további információkat talál a csomópont kontextusában itt
$(document).bind('snow', shovelShow)
parancsot használhatja. Nem kell anonim függvénybe csomagolni.