Ki: az előadó egyszer meghallgathatná magát utólag, ez az éles hangon való kiabálás – legalábbis számomra – nagyon zavaró.
Be: továbbra sem értem a "blokkolástól" való mániákus félelmet (kliensoldalon). A videó példájával élve, amikor lekérem a hálózatról egy adott cég részvényeinek az árfolyamát, akkor ha ezt szinkron csinálom, a felhasználó hiába csinál bármit, amíg meg nem jön a válasz, nem válaszol a böngésző.
Két eset lehetséges:
1, Gyors a hálózat esetén ez nem számít, mert hamar megvan az eredmény, mire a következő elemre viszi az egerét, már frissítettük az adatokat.
2, Lassú hálózat esetén ha a következő funkciókra kattint például, akkor mindegyik helyén ott fog pörögni a töltést jelző animáció egymás után, hisz mindegyikre (nagy valószínűséggel) lassú lesz a válasz.
Ráadásul hiába indítjuk párhuzamosan a kéréseket, ha a szerveroldalon azok a felhasználó munkamenetéhez férnek hozzá, ott elsődleges fontosságú a konzisztencia, azaz ha az első kérés egy változót ír, akkor zárolni kell a munkamenetet a kérés befejeztéig, a második kérésnek meg kell várnia ezt, és csak akkor lehet elkezdeni feldolgozni.
Márpedig – webes alkalmazás esetén – előbb-utóbb, de inkább előbb olyan funkcióba fog botlani a felhasználó, ahol szükség van a netre. Értem én, hogy a felhasználói élmény az rendkívül fontos, node a sok pörgő animáció nem pont ekvivalens az úgynevezett blokkolással?
Szerintem azzal van a gond, hogy a böngészők nem megfelelően kezelik az ilyen helyzetet, és a felhasználó úgy érzi, hogy "lefagyott" az oldal szinkron várakozás esetén. Nekem van egy olyan projektem, amiben szinkron kommunikációt használok, és teljesen jól működik -- kivéve akkor, ha nagyritkán mégiscsak elkényelmesedik a szerver. Ilyenkor a böngésző képes és kezelhetetlen lefagyást jelez a felhasználó felé. (Bár ez egy régi projekt, és lehet, hogy valamit nem vettem figyelembe, ami manapság már javíthatna e helyzeten.)
Bár már számtalanszor leírtam, leírom még egyszer:
1) A hálózat válaszidejére nincs garantált felső korlát. Ha 100ms felett van a válaszidő (ami a hálózat késleltetése + kiszolgálás ideje), akkor azt a felhasználó észreveszi.
2) Blokkolás esetén semmi nem fog pörögni, a böngésző újrarajzolni sem tudja a képernyőt (az egész alkalmazás lefagy).
Nem azért használunk aszinkron kéréseket, hogy párhuzamosan többet is tudjunk futtatni, hanem azért, hogy az alkalmazás reszponzív maradjon.
1, Mi van akkor, ha észreveszi? Tud-e tenni bármit is ellene? Ha a következő használandó funkció hálózathoz fordul, van-e értelme bármit is tennie (lásd 1-es hozzászólásom 2-es pontja)?
Az XMLHttpRequest objektumnak van timeout tulajdonsága.
2, Most próbáltam ki, Firefox 35 és Opera 12 alatt folytatódnak az animációk, Chrome 24 alatt nem (feltételezem, hogy újabbak alatt igen) – az animációk rajzolásának egyébként sem kéne közük legyen a JS-hez.
<html> <style> #animacio { width: 16px; height: 16px; } </style> <body> <div id="animacio"></div> <button id="gomb">Gomb</button> <script> function tolt() { animacio.style.backgroundImage = 'url(\'ajax-loader.gif\')'; var xhr = new XMLHttpRequest(); xhr.open("GET", 'lassu.php', false); xhr.send(null); animacio.style.backgroundImage = 'none'; } var animacio = document.getElementById('animacio'); var gomb = document.getElementById('gomb'); gomb.onclick = tolt; </script> </body> </html>
A timeout szinkron esetben hogyan működik?
Például beállítok egy rövid timeoutot, amin túllóg a szerver válaszideje. Ha mégis végrehajtódik a szerveroldalon a művelet, és válaszolna, akkor a szerver válasza elvész, vagy mégis jöhet egy hívás egy callbackre?
Na jó, ez így zavaros, már olyan rég használtam szinkront ilyen esetben, hogy elsőre elfelejtettem, hogy nincs is callback. De éppen lehetne, timeout után. Vagy a timeout esetén hívódhatna meg egy callback, ami vagy lezárná a hívást, vagy tovább várna, aszerint, amit akarunk.
Na mindegy, összességében nem túl nagy lenne a nyereség, maradok az aszinkronnál, már hozzászoktam.
1, Mi van akkor, ha észreveszi? Tud-e tenni bármit is ellene? Ha a következő használandó funkció hálózathoz fordul, van-e értelme bármit is tennie (lásd 1-es hozzászólásom 2-es pontja)?
És mi van akkor, ha a következő használandó funkció nem fordul a hálózathoz? Nézze tétlenül a gif animációkat, mert azok legalább működnek? Szerintem inkább keres egy másik alkalmazást, ami reszponzív (ha nincs monopol helyzet; ha az van, akkor csak gondol arra, hogy lecserélné).
Én például szeretem az olyan webmail klienst, ahol miután "elküldtem" egy levelet, egyből olvashatom a korábban letöltött másik/következő levelet, vagy elkezdhetem írni rá a választ, vagy új levelet, használva az esetleg JS-t is hasznosító szerkesztőfelületet.
Felteszel sok "mi van, ha?" kérdést, és csak azokat az opciókat veszed figyelembe, amik a te álláspontodat látszanak igazolni. De minden "mi van, ha?" mellet ott van egy "mi van, ha nem?" kérdés is. Jelen esetben a te javaslatod, míg az első esetet látszólag szebben megoldja, a másikra egyáltalán nem nyújt megoldást. Én inkább azt a megközelítést választanám, ami több használati esetet megold, mert ha csak kalapácsom van, akkor csak kalapálni tudok, míg ha egy összetettebb szerszámom, akkor mást is (ehhez persze meg kell tanulni a szerszám használatát, de valamit valamiért).
Az XMLHttpRequest objektumnak van timeout tulajdonsága.
Erről a Firefox ezt gondolja:
Use of XMLHttpRequest's timeout attribute is not supported in the synchronous mode in window context.
De még ha használható is lenne a timeout, az milyen felhasználói élmény, hogy ha 30 másodperc helyett 31 alatt érkezne meg a válasz, akkor dobjuk el az egészet, hogy várnom kelljen még egyszer 30 másodpercet semmittevéssel töltve, reménykedve, hogy a megengedett idő alatt ezúttal megjön a válasz, ahelyett, hogy teszem a dolgom az első 31 másodperc alatt, és kapok értesítést, hogy folytathatom azt a szálat, ami esetleg függöt tőle? Szerintem olyan, amit gondolkodás nélkül lecserélek.
Ráadásul öt perc alatt kiderült, hogy az állításoddal ellentétben a böngészőkben már megoldották a blokkolás problémáját.
Tehát örüljek annak, hogy mennek a gif animációk és esetleg tudok görgetni, de ha bármi mást szeretnék csinálni, ami JS alapú, akkor ne is álmodjak róla, mert annak úgysincs értelme, mert hátha a hálózatra vagy egyéb szekvenciális függőségre lenne hozzá szükség?
Szerintem ezt ne a nyelv/futtatókörnyezet döntse el, hanem az aktuális alkalmazás az üzleti logika alapján. Igen, ehhez az üzleti logikát szükséges a gép nyelvére lefordítani, de mintha ez lenne a munkánk.
Továbbá ismét a Firefox konzol üzenetét idézném, amit szinkron XHR hívás esetén ír:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/
Ha nem kérdőjelezzük meg folyamatosan magunkat és a tudásunkat, akkor maradunk szépen a kőkorszakban.
Ennek a lónak is van egy másik oldala, ahova ha átesünk, akkor szintén a kőkorszakban maradunk.
És mi van akkor, ha a következő használandó funkció nem fordul a hálózathoz?
A példáddal élve: hiába írod meg a következő levelet, az ugyanúgy nem fog elmenni.
Egy levélküldésnél valószínűleg egyébként nyugodtan használhatsz aszinkron kéréseket, csak ne feledd el, hogy ez egy nagyon primitív funkció. Amint olyan adathalmazzal dolgozol, ahol összefüggéseket kell kezelni (egy helyen átírsz valamit, és a másik helyen is frissíteni kell), pont a fenti eset fog előállni, hogy hiába küldesz el párhuzamosan több kérést, a szerveroldalon csak sorosan tudod kiszolgálni a megosztott memória (munkamenet) miatt.
De még ha használható is lenne a timeout, az milyen felhasználói élmény, hogy ha 30 másodperc helyett 31 alatt érkezne meg a válasz, akkor dobjuk el az egészet
Timeout-ja van az AJAX kéréseknek is, és ha lejár, akkor pontosan ugyanúgy eldobja a böngésző az eredményt, ha ezt túllépjük. Tehát a két megoldás ekvivalens.
Tehát örüljek annak, hogy mennek a gif animációk és esetleg tudok görgetni
Ez a feladattól függ, lásd első válaszom.
Egyébként pedig nem az aszinkron hívásokkal van feltétlenül bajom ("továbbra sem értem a "blokkolástól" való mániákus félelmet"), hanem azzal, hogy a szinkron hívást nem használják, pedig bizonyos összetettség felett csak ennek van értelme.
a szerveroldalon csak sorosan tudod kiszolgálni a megosztott memória (munkamenet) miatt
Miért is? Miért lenne korlátozó tényező a megosztott munkamenet? Miért ne lehetne párhuzamosan X+1 szerver ami kiszolgálja a kéréseket, és ugyanazt a munkamenetet használja valamilyen memória adatbázisban (Redis, memcached)?
Ennél azért vannak finomabb módszerek, úgyhogy szerencsére azért nem csak sorosan működhet a feldolgozás. Persze ha pont "ugyanazt" módosítják, akkor marad a soros feldolgozás, legalábbis a módosítás idejére. Kellhet exclusive lock, de azért van pár más opció.
A példáddal élve: hiába írod meg a következő levelet, az ugyanúgy nem fog elmenni.
Nem feltétlenül elküldeni akarom, hanem megírni. Ha blokkol az alkalmazás, akkor amíg az első levél el nem ment, addig írni sem tudok, csak várni. Ha az animációkat is kikapcsolhatóvá akarjuk tenni a környezet védelmében, akkor miért akarjuk tétlenségre kényszeríteni a felhasználókat ahelyett, hogy haladhatnának a dolgukkal, amikor lehet?
Amint olyan adathalmazzal dolgozol, ahol összefüggéseket kell kezelni (egy helyen átírsz valamit, és a másik helyen is frissíteni kell), pont a fenti eset fog előállni, hogy hiába küldesz el párhuzamosan több kérést, a szerveroldalon csak sorosan tudod kiszolgálni a megosztott memória (munkamenet) miatt.
És mi van, ha nem olyan adathalmazzal dolgozol?
Timeout-ja van az AJAX kéréseknek is, és ha lejár, akkor pontosan ugyanúgy eldobja a böngésző az eredményt, ha ezt túllépjük. Tehát a két megoldás ekvivalens.
Az eldobás szempontjából ekvivalens, viszont aszinkron hívás esetén engedem a felhasználót mással foglalkozni, ha tud. Ha nem tud, akkor úgy írom meg az alkalmazást, hogy ne tudjon, jelezve, hogy várnia kell a szerverre. De nem úgy, hogy blokkolom az UI 99%-át.
Egyébként pedig nem az aszinkron hívásokkal van feltétlenül bajom ("továbbra sem értem a "blokkolástól" való mániákus félelmet"), hanem azzal, hogy a szinkron hívást nem használják, pedig bizonyos összetettség felett csak ennek van értelme.
A szekvenciális végrehajtás mióta egyenértékű a blokkolt felhasználói felülettel/alkalmazással? Vannak remek adatszerkezetek és módszerek, amik biztosítják az egymásutániságot úgy, hogy nem blokkolják a felületet és engedik a lehetséges párhuzamos folyamatok futását.
Nem feltétlenül elküldeni akarom, hanem megírni. Ha blokkol az alkalmazás, akkor amíg az első levél el nem ment, addig írni sem tudok, csak várni.
(És ez válasz az összes felvetésedre:) Mint fentebb írtam, bizonyos összetettség felett van értelme a szinkron hívásnak. Egy űrlap kitöltésénél elküldhetek egy aszinkron kérést a mező ellenőrzésére, és közben a felhasználó nyugodtan gépelhet, lelke rajta. De egy számla tételsorán ha átírnak egy összeget például, akkor frissíteni kell egy csomó kapcsolódó űrlapot, itt bizony nem kattintgathat ész nélkül addig, amíg meg nem érkezik a válasz, különben inkonzisztens adatok fognak megjelenni a képernyőn.
Ha a böngésző jól kezelné, akkor számos esetben a felhasználói élmény ugyanaz lenne mint aszinkron esetben, amikor úgyis egy modal ablakra egy várakoztóanimációt teszek.
Szerintem az zavart meg, hogy mindenki a hálózat lassúságáról beszélt, holott a válasz idejéről van szó. Márpedig az nem csak a hálózat sebességétől függ, mert a válaszidő mint olyan nem egy, a router-re írt szám, hanem a ténylegesen megtapasztalható idő.
Azt írod két eset lehetséges, holott pont nem. Vagyis neked igazad van, mert Te az átlagról (hálózat sebességéről) beszélsz. Ha onnan nézem tényleg mindegy, hogy mi van. És igazad is van, ha nem túl nagy a szórás az értékek között.
Sajnos azonban az életben nem így van, mert van bizony olyan, hogy egy-egy kérésre igencsak későn érkezik a válasz. Ezek a késő válaszok pedig szinkron esetén bosszúságot okoznak a felhasználónak, mert a gyors válaszok elkényelmesítették, és nem fogja érteni, hogy ami eddig pikk-pakk az most miért nem, meg mi van, kattintottam héé.
És ezek azok az apró bosszúságok amik a felhasználói élményt lerontják. Ezen tud segíteni az aszinkron kiszolgálás, mert mire észrevennéd, hogy para van, már nincs is.
Az emberi elme meg hekkelhető, mert attól, hogy nincs ott a válasz egészben, de elkezdett megjelenni, azaz érzésed van, hogy történik valami. Ugyan úgy, mint amikor kölcsönadsz 100 forintot valakinek, és ő a határidőre csak 10-et törleszt, aztán a rákövetkező héten megint 10-et és így tovább, sokkal jobban elviseled, mint mikor 10 hét késéssel adja vissza az egész lóvét. Tölts egy fészbúk oldalt, ott is a tényleges tartalom megjelenéséig nagyon sokat kell várnod, holott az az érzésed, hogy pikk-pakk, és képes vagy várni több mint 3 másodpercet. Holott 5 másodperc fehér képernyő után biztos bezárnád a böngésződet, hogy ez nem megy.
pp
Az előadó testi adottságaira tett megjegyzéseid nem valóak egy szakmai oldalra. Ezek ugyanis nem az előadót, hanem téged minősítenek. Kérlek az ilyen megjegyzéseket - ha már a szerkesztők nem figyelnek erre -, hanyagold ezen a szakmainak gondolt oldalon. Köszönöm.
Nem zavart meg. Mint írom (nem is egyszer, a többieknek válaszként), vannak olyan esetek, ahol nincs értelme annak, hogy a felhasználó tovább folytassa a "munkát". Ilyenkor az aszinkron kérések ekvivalens, de inkább rosszabb "felhasználói élményt" adnak (tele a képernyő pörgettyűkkel), mint a szinkron. Súlytalan feladatoknál (mező értékének szintaktikai ellenőrzése) mindenképp jobb az aszinkron.
Félig ki: A facebook-os példád abból a szempontból rossz, hogy ha a teljes HTML-t egyben küldenék le, és nem n darab párhuzamos kérést indítanának, akkor jóval gyorsabban menne például a kezdőlapjuk megjelenítése.
Az előadónak a hanghordozása nem testi adottság, hanem tanult és tanulható tulajdonság. Nagyon zavaró volt végighallgatni így a prezentációt. Ahogy Ádám is minőségibb írásokat kér, ha van alternatíva, inkább azt kérném beküldeni.
"Félig ki: A facebook-os példád abból a szempontból rossz, hogy ha a teljes HTML-t egyben küldenék le, és nem n darab párhuzamos kérést indítanának, akkor jóval gyorsabban menne például a kezdőlapjuk megjelenítése."
Nem tudom. Talán azért, mert nem értenek hozzá. A böngészőből indítani n kérést mindig jóval drágább, mint házon belül összeszedni a tartalmat, és egyben kiküldeni. Majd ha elterjed a HTTP 2.0, akkor valamivel jobb lesz a helyzet.
Én is leírtam, hogy miért rossz a példa. Mit szeretnél ebből az egészből kihozni? Azért így csinálják, mert úgy gondolják, hogy jó. De mivel a böngészők másfél évtized óta képesek arra, hogy progresszíven rendereljék le a HTML-t, miközben jön le, nem nagyon látok érvet a facebook megoldása mellett. Miért? Mert egy kapcsolaton lecsorgó HTML-t gyorsabb feldolgozni, mint n kapcsolaton lejövő JS-t.
Írtam egy példát, arra, hogy bár "egy kapcsolaton lecsorgó HTML-t gyorsabb feldolgozni, mint n kapcsolaton lejövő JS-t", mégis van aki használja (nem is kis cég) a felhasználói élmény javítása szempontjából.
Erre írod, hogy rossz a példa, gondoltam azért rossz, mert szerinted nem a felhasználói élményt akarják javítani. Erre kérdeztem rá, hogy akkor szerinted mi a pékért csinálják így, ha nem ezért. Gondoltam tudsz erre választ adni, ezért a sok kérdés.
"nem nagyon látok érvet a facebook megoldása mellett"
És amit én írtam, hogy a felhasználóban azt az érzetet keltsék, hogy valami történik? Az nem lehetséges?
Megnéztem, hogyan működik, két kérésben van benne a tartalom (bootstrap.php), ezekben van benne a kezdőlap minden adata, ezekből állítják elő a HTML-t. Magyarul egyáltalán nem a felhasználói élmény fokozása volt a fejlesztők célja.
Ilyenkor az aszinkron kérések ekvivalens, de inkább rosszabb "felhasználói élményt" adnak (tele a képernyő pörgettyűkkel), mint a szinkron.
Máshol meg ezt:
Még jópár évvel ezelőtt az egyik hardverkereskedőtől le lehetett tölteni az árlistáját, ami egy többmegabájtos HTML volt, ráadásul akkor még jóval lassabb volt az internetelérés sebessége.
Ami nagyon sokat dobott az egészen, hogy letöltés közben a böngésző címsorában folyamatosan kijelezte, hány százaléknál tart.
Most akkor az a jó, ha van pörgettyű/folyamatjelzés vagy az, ha befagy az oldal?
Nem ekvivalens a két példa. Az elsőben, ha tele van a képernyő pörgettyűkkel, akkor aszinkron kérés esetén azt jelenti, hogy bedugult a hálózat. Nem hordoz senki számára plusz információt, hogy n darab csiga jár körbe, ezért elég egy is. Ráadásul az is kiderült, hogy szinkron kérés esetén is lehet animálni.
A kereskedős példában pedig folyamatosan jön az anyag.
Ki mondta, hogy az aszinkron kérésben nem jöhet folyamatosan anyag? Valamint hiába tudsz kirakni egy animált gifet szinkron hívásnál, ha a folyamat állapotáról nem tudod tájékoztatni a felhasználót, hiszen úgy hallottam, hogy
Nem hordoz senki számára plusz információt, hogy n darab csiga jár körbe
Aszinkron hívásnál folyamatosan tudod frissíteni az állapotot. Szinkronnál erre nincs lehetőséged.
Látod, ez egy nagyon jó felvetés. Ha a böngészőgyártóknak sikerült azt megoldaniuk, hogy szinkron kérés mellett folytatódhassanak az animációk, kis munkával járna valamilyen módon egy %-ot kijelezni, már ha erre szüksége van a kliensnek.
kis munkával járna valamilyen módon egy %-ot kijelezni, már ha erre szüksége van a kliensnek.
Mihez képes kis munkával? Ha nem tudjuk mennyi idő múlva jön vissza a tartalom, és nem tudjuk, mekkora a tartalom mérete, és milyen gyors az adatátvitel, nem tudom, honnan tudnánk kis munkával kiszámolni és kijelezni a százalékos értéket, főleg akkor, ha szinkron kérésről van szó.
Ha nem tudod a tartalom méretét, akkor aszinkron kérés esetén sem tudod kijelezni a százalékot. De szerencsére ott van nekünk a header('Content-Length: 12345');
És szinkron kód esetén hogyan is fogod olvasni a fejléceket? Egyébként én nem is mondtam hogy ki lehetne jelezni a százalékot, mert nem lehet, te mégis írtad, hogy lehet. De mivel a %-ot csak az idő függvényében van értelme kijelezni, így nincs igazán értelme (mert legfeljebb azt tudná valaki kijelezni, hogy mennyi adat jött le a mennyiből, aminek csak érintőlegesen van köze az időhöz TCP/IP esetén és nem tudjuk, mennyi ideig tart a maradék adatot megkapni).
Majd a böngésző olvassa és kezd valamit a százalékkal. Az időfaktort pedig te hoztad be. De mivel a hálózat sebessége nem megbízható, nincs is értelme számolni vele, elég tudni a teljes/letöltött bájtok számát.
Ez általában így van, de ha nincs más információ, csak az, hogy %-ban vagy byte-ban hol tart a folyamat, amire várni kell - akkor érdekli ez is. Főleg ha csak ez az adat van.
Szerintem elment a téma olyan irányba, ahol a (böngészőkben jelenleg implementált, xmlhttpreq) szinkron módszer nem jó. Ha sok az adat ami lejön és közben vissza kell jelezni, az tök más, mint amikor arról beszélünk, hogy egy rövidke valami lejöhet-e szinkronban is.
Ha itt 2015-ben az aszinkron hívások létjogosultságáról kell meggyőzni (kevés sikerrel) embereket, akkor úgy érzem, hogy rossz helyre küldöm a blogmarkokat...
Attól, hogy Gábor minden alkalommal szükségét érzi hirdetni a saját minimalista megközelítését, a többi sokszáz olvasó még biztos, hogy értékeli a blogmarkod. Én mindig örülök, ha látom, hogy te küldtél valamit, mert tudom, hogy érdekes lesz.
PHP-ban dolgozol, mert ugyanaz a feladat C++-ban sokkal több kódot igényel. A CSS és JavaScript újdonságokat viszont, amik épp azt teszik lehetővé, hogy kevesebb kóddal valósítsunk meg korábban több kódot igénylő dolgokat, meg szükségtelennek tartod, mert nélkülük is elvégezhető a feladat.
Az a baj, hogy a saját szubjektív absztrakciós szinted valamiféle objektív dolognak tartod, és ementén ítélsz meg minden technológiát. Ha már úgyis szereted az egyházi tematikájú metaforákat, inkvizícióval és eretnekekkel, akkor azt kell hogy mondjam, olyan vagy mint a bigott protestáns, aki meg van róla győződve, hogy a katolikus és az ateista is a pokolra jut.
A példád rossz. A PHP egy adott környezet, ami tizenvalahány éve létezik, és pontosan tudjuk, hogy erőforrásigényes, de termelékeny.
A HTML, CSS és JS "újítások", "szabványosítás" bevezet egy újabb szintaxist az adott dologra (átnevezés). Vegyük például az AJAX hívást: régi IE-ken a megfelelő ActiveX-et kellett létrehozni, míg más böngészőkön már ott van az XMLHttpRequest objektum. Viszont életemben elég egyszer megírni egy függvényt, ami megvalósít egy funkciót, onnantól kezdve semmi mást nem kell tennem, mint beinclude-olni, és működni fog. A szoftvermásolás egy kvázi ingyenes dolog.
Magyarul pontosan ugyanannyi munkával jár az adott funkció használata bármely környezetben és bármely időpontban, legyen az szabványos vagy sem. Kit érdekel, hogy pár tíz sorral több a kód, és van benne egy detektálós rész, ami pár if-ből áll? Senkit.
Ebből következik, hogy ez az egész "szabványosítás" értelmetlen, és elveszi az időt sokkal fontosabb dolgoktól. Az Irányváltásban sem válaszolt senki arra a felvetésre, hogy az interneten növekvő tartalmi mennyiség feldolgozására nem született technológia. A webhelyek száma megtizenhatszorozódott az utóbbi tíz évben, de nekünk van tizenhatszor annyi időnk látogatóként, hogy ezeket átfésüljük, ha keresünk valamit? Nincs. Tizenhatszor jobb lett a Google? Nem. Akkor miért pazarlunk egy másodpercet is "szabványosításra", ha úgysem nyerünk vele semmit, csak inkompatibilitást?
Ezeken kéne a tisztelt katolikusoknak és ateistáknak elgondolkodni.
A PHP egy adott környezet, ami tizenvalahány éve létezik, és pontosan tudjuk, hogy erőforrásigényes, de termelékeny.
Mi teszi termelékennyé?
Vegyük például az AJAX hívást
Ne vegyük az AJAX hívást. Vegyük például a lekerekített sarkokat. Mennyi CSS, HTML és képfájl kellett hozzá mielőtt egyetlen sorból meg lehetett oldani?
Viszont életemben elég egyszer megírni egy függvényt, ami megvalósít egy funkciót, onnantól kezdve semmi mást nem kell tennem, mint beinclude-olni, és működni fog.
Mert a szoftvert mindenki arról ismeri, hogy elég egyszer megírni, és soha többet nincs vele dolog.
A szoftvermásolás egy kvázi ingyenes dolog.
A legkevésbé sem az, ha hálózaton kell utaztasd, parzolnod kell, memóriában kell tartsd és újra és újra ki kell értékeld.
Magyarul pontosan ugyanannyi munkával jár az adott funkció használata bármely környezetben és bármely időpontban, legyen az szabványos vagy sem. Kit érdekel, hogy pár tíz sorral több a kód, és van benne egy detektálós rész, ami pár if-ből áll? Senkit.
És ha jön egy új böngésző, amiben megint másik felületen keresztül érhető el ugyanaz a funkció, akkor beleírsz egy újabb if-et? Ez pontosan hogyan viszonyul a csak egyszer kell megírni elvéhez?
Ebből következik, hogy ez az egész "szabványosítás" értelmetlen, és elveszi az időt sokkal fontosabb dolgoktól. … Akkor miért pazarlunk egy másodpercet is "szabványosításra" … ?
Komolyan azt gondolod, hogy azok az emberek, akik rendelkeznek az általad vizionált nagy kereshető adatháló megvalósításához szükséges elméleti háttérrel, azok csak azért nem valósították eddig meg, mert még mindig azt tárgyalják, hogy mi legyen a színátmenetek szintakszisa?
Az Irányváltásban sem válaszolt senki arra a felvetésre, hogy az interneten növekvő tartalmi mennyiség feldolgozására nem született technológia. A webhelyek száma megtizenhatszorozódott az utóbbi tíz évben, de nekünk van tizenhatszor annyi időnk látogatóként, hogy ezeket átfésüljük, ha keresünk valamit?
Négy és félezer év alatt a könyvtárakban hányszorosára nőtt az írott szöveg óceánja? Mégsem született rá eljárás, hogy kereshető legyen. Lehet, hogy ez a probléma valamivel összetettebb, és valószínűleg ahhoz sincs köze, hogy a nyomdászok és rézmetszők a maguk dolgát végezték, és nem ezen dolgoztak.
Hagyjuk már ki a felesleges köröket! Egyrészt pontosan tudod, hogy a PHP-hoz képest C-ben vagy Javában mennyi boilerplate van, másrészt ha ebből arra szeretnél rávezetni, hogy nade most már a HTML, CSS, JS-ben is ennyivel jobb, mert a szabványosítás miatt kevesebbet kell gépelni, akkor vegyük sorra az érveidet:
lekerekített sarkok: egy weboldal frontend elkészítése idejének hány százalékát teszik ki a lekerekített sarkok elkészítése?
»Viszont életemben elég egyszer megírni egy függvényt, ami megvalósít egy funkciót, onnantól kezdve semmi mást nem kell tennem, mint beinclude-olni, és működni fog.«
Mert a szoftvert mindenki arról ismeri, hogy elég egyszer megírni, és soha többet nincs vele dolog.
Miért kevered ide a szoftvert, amikor függvényről beszéltem? Ha abban megírok egy ágat az IE6 AJAX kezelésére, kitesztelem, és jó, akkor ahhoz soha többet nem kell nyúlni.
Azon a szinten, amiről beszélünk, szolgáltatásonként pár kilobájtról van szó. A mai hardverek és hálózati sebesség, gyorstárak világában nem okoz gondot ezek kezelése.
És ha jön egy új böngésző, amiben megint másik felületen keresztül érhető el ugyanaz a funkció, akkor beleírsz egy újabb if-et?
Igen. Megírom, letesztelem, kész, mehetünk tovább. Most is ez megy, lásd különböző böngészők új funkciói.
csak azért nem valósították eddig meg, mert még mindig azt tárgyalják, hogy mi legyen a színátmenetek szintakszisa
Nem. Az XHTML és a szemantikus web 1.0 azért bukott meg, mert túl bonyolult (nézz meg egy rdf-fel felturbózott html kódot). Ekkor jöttek képbe az új böngészők, és a világ elment inkább a szabványosítás felé, ahelyett, hogy egy egyszerűbb szemantikus weben dolgozott volna. Egyszerű matek, hogy miért volt rossz választás:
- hány százalékkal lett kevesebb munka a frontenden a HTML/CSS/JS szabványosítása miatt?
- hány százaléka a frontend egy teljes website elkészítési költségének?
- egy website-ra – teljes életciklusában – fordított összeg hány százaléka a frontend fejlesztés, és ezen belül mennyit nyertünk a szabványosítással?
Érzésem szerint nagyjából 1-2%-nyit. Tedd mellé a fenti tizenhatos számot, ami százalékban 1600, és rögtön igazolódik, hogy a szabványosítás a lehető legrosszabb döntés volt, amit a fejlesztők hozhattak. Hogy miért? Lásd lentebb.
Négy és félezer év alatt a könyvtárakban hányszorosára nőtt az írott szöveg óceánja?
Ez a baj, hogy a fejlesztők még mindig az analóg világ metaforáiban gondolkodnak, ezért dolgozunk még mindig dokumentumokkal, és nem adatokkal. Már egy SQL adatbázis is űrtechnológia a kőkorszaki HTML-hez képest, hisz minden mező meg van nevezve. Használjuk már ki a számítástechnika adta előnyöket! Jelöljünk meg mindent, és rögtön kereshetővé válik.
Religion is like a penis. It’s fine to have one. It’s fine to be proud of it. But please don’t whip it out in public and start waving it around. And please don’t try to shove it down my children’s throats.
Ez bölcs és szellemes gondolat, de fordítsuk meg a dolgot. Amikor én azt állítom például, hogy az oop korlátozottan használható, vagy hogy az eseményvezérelt, aszinkron szerveroldali JS-nek sok értelme nincs, akkor mindig megjelenik három-négy ember, aki az ellenkezőjét bizonygatja. Most akkor ki a vallásos? Miért nem lehet kérdéseket feltenni bizonyos témákban? Miért nem lehet rámutatni a gyenge pontokra?
Amikor a téma arról szól, hogy az OOP korlátozottan használható, akkor miért ne vágna a témába, ha valaki szerint ez nem így van? Nyilván témába vág, tehát a három-négy ember, aki megjelenik, jó helyen jár.
Ha arról beszélünk, az OOP-ben hogyan oldható meg egy konkrét probléma, vagy miért fontosak a SOLID elvek, majd minden alkalommal megjelenik valaki, aki litániákat ír arról, hogy az OOP egyébként korlátozottan használható ezért és ezért, akkor egy idő után joggal merül fel a gyanú, hogy az illető fejében valami el van tájolva.
Furcsállom, hogy a különbség elsőre nem egyértelmű.
Tegyük fel, hogy kielégülésre vágysz, és ehhez fogsz egy sajtreszelőt, mert mindenki azt mondja, hogy ezzel a legjobb. Mivel úgy érzed, az eredmény nem feltétlenül annyira kellemes, feljössz a fórumra, és megkérded, hogyan kell helyesen csinálni. Ilyenkor melyik válasz a jobb: tartsd máshogy, vagy pedig az, hogy nem a legjobb segédeszközt választottad ki?
tegyük fel, hogy ezekről beszélünk, van akit érdekel az anal, vagy teljesen újfajta területet fedezne fel, erre jössz és azt mondod, hogy ne baszakodj már vele, mert handjob-bal tökéletesen ki lehet elégülni, és annál (anál :D) jobb nincs.
A szál már az első hozzászólástól kezdve off, talán a 80. környékén volt 3-4 témába vágó hozzászólás, azt hiszem :). Emiatt hördültem fel, mert hülye fejjel végigolvastam.
Nekem az jut eszembe, hogy amikor még PHP-ztam, a különféle PHP-s fórumokon is mindig volt valami fanatikus, aki kötelességének érezte minden témában megjegyezni, hogy ne használj PHP-t és akkor nem lesz ilyen gondod. Ezt hívom hittérítő típusnak.
Ha az a téma, sajtreszelővel hogyan lehet a kívánt hatást elérni, akkor azt célszerű tiszteletben tartani. Ha az a téma, mi a legalkalmasabb mód a kielégülésre, mindenki azért van ott, hogy ezt kitárgyalja, lesz aki a sajtreszelő mellett érvel, lesz aki ellene. Nem tudom, mit tehetnék még, hogy megértsd (persze nyilván érted, én meg ennek ellenére leállok veled ilyen hülyeségeken, de egye fene, játsszunk).
Ha valaki kérdést tesz fel, mert teszem azt kezdő, lehet neki tippeket adni, hogy sajtreszelő helyett használhatna inkább mást. Ez nyilván teljesen más eset.
az aszinkron hívások létjogosultságáról kell meggyőzni (kevés sikerrel) embereket
Azért annyira nem erőltetted meg magad, hogy a felmerült kérdésekre válaszolj. Ráadásul öt perc alatt kiderült, hogy az állításoddal ellentétben a böngészőkben már megoldották a blokkolás problémáját.
Mint fentebb levezettem, teljesen indifferens az esetek túlnyomó többségében, hogy aszinkron kéréseket indítsanak, mert pont ugyanaz lesz a végeredmény, mintha szinkron lett volna. Ebben az esetben viszont miért szenvedjünk az aszinkron programozás hátrányaival?
When best practices are treated as a final solution, questioning them is not allowed. If we cannot question the reasons behind a specific best practice, we cannot understand why it is better than the other available solutions.
This means that we lose the opportunity to learn and improve the current situation.
Ez egy nagyon fontos mondat. Ha nem kérdőjelezzük meg folyamatosan magunkat és a tudásunkat, akkor maradunk szépen a kőkorszakban.
úgy érzem, hogy rossz helyre küldöm a blogmarkokat
Szerintem nagyon jó helyre érkeznek a blogmarkok, mert arra ösztönzi az embereket hogy átgondolják a node.js-sel kapcsolatos álláspontjukat. A projekt egyre több sebből vérzik, erre nagyon jól sikerült rámutatnod, így könnyebb lesz döntést hoznunk, ha legközelebb új munka technológiai alapjait kell kiválasztani.
Én az utóbbi időben az egész PHP használatát kérdőjelezem meg. Mert sokkal hasznosabb dolgokra tudom használni a gép CPU-ját és memóriáját, mint egy Apache HTTPD és PHP kód folyamatos újrapörgetésére.
A PHP egy rendkívül termelékeny szoftver, gyorsan lehet vele fejleszteni. Nyilván lassú és erőforrásigényes, de ezzel csak akkor kell foglalkozni, ha problémát jelent. A többdimenziós asszociatív tömbök és a szemétgyűjtés kombinációja együtt mindent ütnek.
Nem hiszem hogy arról lenne szó, hogy bárkit győzködni kéne az aszinkron műveletek hasznosságáról, hiszen mindenki érti és használja -- és próbálja fejleszteni, ami nagyon jó. Épp az aszinkron elterjedtsége miatt lett fekete bárány a szinkron hívás, pedig sok esetben ez utóbbi is jó lenne, ha kicsit foglalkoznának ezzel is, fejlesztenék, figyelnének rá. Mindenki (én is) egyszerűbbnek tartja megoldani a "hagyományos aszinkron" módon, pedig lehet, hogy lennének előnyei a szinkron műveleteknek is, ha a hátrányait sikerülne kiküszöbölni (mondjuk az kérdés, hogy megéri-e a fáradságot).
Ha itt 2015-ben az aszinkron hívások létjogosultságáról kell meggyőzni (kevés sikerrel) embereket, akkor úgy érzem, hogy rossz helyre küldöm a blogmarkokat...
Sajnos teljesen igazad van. Bár részemről nagyon örülök a blogmarkjaidnak, általuk (és néhány más blogmark által) a Weblabor legalább marginálisan érint modern webbel kapcsolatos témákat is. De most már be kell ismerjem magamnak, mindig hibát követek el, amikor érdeklődéssel telve elolvasom a hozzászólásokat egy ilyen előremutató, fontos blogmark alatt. Egyszerűen időpazarlás. Már megint és megint ugyanaz a lemez, egyetlen embernél beakadva, és mindenki neki próbálja elmagyarázni az alapokat. Erről szól a hozzászólások 100 %-a.
Áthelyezve kicsit a nézőpontot, tegyük fel, van egy receptoldal. Szeretnék valami jó receptet, amiben van tojás. Elolvasnám a hozzászólásokat is, mert feltételezem, hogy az adott receptről szólnak, mindenki leírja a tapasztalatait, biztosan megtudok olyat, aminek hála még sikeresebben használhatom a receptet, esetleg vitákat olvashatok a hozzáadott majoranna mennyiségét illetően (főleg mivel a régebbi receptek alatt mindig tanultam valami újat). Azonban mindez hiú ábránd, mivel valami megszállott minden receptet teleszpemmel azzal, hogy a tojás nem egészséges. Persze csakis a közös jó érdekében, hogy mindenki végre észbekapjon.
Nem kell túl komolyan venni ezt a hozzászólást persze. Itt az a furcsa "ügyfél" vagyok, aki nem hagyja ott az egészet a francba, hanem valami érthetetlen oknál fogva marad és időnként leírja, mi nem tetszik neki, nem mintha bármi változna tőle. Tessék ignorálni, az lesz a legjobb.
Nem vagyok belsős, így lehet nem tudok róla, hogy ez a Hidvégi valami VIP, vagy nemzetközi szaktekintély, vagy valakinek a valakije (mivel többször lett kérve, hogy vegyen vissza, de ezt leszarhatja minden következmény nélkül), de én unom a feltűnési viszketegségét és azt, hogy bármekkora zseninek képzeli magát, képtelen használni egy egyszerű fórumot. Ti. nyiss egy témát, ne pedig minden más témát offolj szét a hülyeségeiddel.
Nem feltétlenül várok erre válaszokat, csak le kellett írnom.
- meg nem értett zseni, mint pl Liszt Ferenc, aki bizonyos dolgokban iszonyatosan megelőzte korát és a kortársak nem értették meg
- hobbija vagy munkája az érveléstechnika, annak is az a része, hogy hogyan lehet egy vitát hatékonyan elterelni a lényegről. tulajdonképpen jól fizetett tanácsadó valamely politikai pártban, és itt edz.
Eleinte én is csak csendben figyeltem, hátha Liszt Ferenc. Egyrészt arra jutottam, hogy szerintem egyértelműen nem az, másrészt ha az is lenne, attól még a kortársak nem fogják (fogjuk) megérteni, tehát semmivel nem jutunk előrébb, ha hagyjuk minden témát teleprédikálni.
A másik két kategóriát meg gondolkodás nélkül moderálnám :).
Ne haragudj, de tőled aztán konstruktív, megoldásra mutató comment nemigen látható.
Mindig az "ez se tetszik, az se".
Szerinted ez mennyire jobb? Gábor legalább segít is a kezdőknek és érdekes dolgot is szokott írni.
Továbbra sem értem, hogy szerveroldalon miért nem használnak pszeudo-blokkoló függvényeket? Jelenleg a node úgy működik, hogy amikor IO művelet következik, akkor a vezérlés visszakerül a node.js-hez, majd az IO végén meghív egy callback függvényt, aminek átadja az adatokat.
Miért nem az történik, hogy az adatok megérkezésekor visszakerül a vezérlés a hívó függvényhez? A hibaüzenetet meg mondjuk el lehetne érni egy függvénnyel vagy egy rendszerkonstanssal:
var fajl = file_read('akarmi.txt'); if (fajl === null && get_last_error() === FILE_NOT_FOUND) { console.log('hehe'); }
Ha ezt megcsinálnák, nem kéne változtatni a szabványon, és nem kéne foglalkozni a videóban felsorolt problémák egyikével sem.
A google-t sosem érdekelték annyira a leírt szabványok, hogy ne lehessenek úttörők, lásd SPDY.
Ráadásul ez olyan szabványváltoztatás, ami a JS kódereket nem érinti, a V8-ban egy óra alatt elvégzik a változtatásokat, és megúsznak hat év útkeresést.
Ezt visszafelé kompatibilis módon nem lehet megcsinálni.
var foo = 1234;
var content = readFile('file.txt');
console.log(foo, content);
Itt a várt eredmény az, hogy a foo értéke nem változik meg (hiszen szinkron a kód), ha a readFile nem nyúl hozzá. Ha a vezérlés visszakerül az event loopba, akkor a foo változhat.
Pont ezt oldották meg az async-await konstrukcióval (ami mellesleg a C#-ból lett egy-az-egyben átvéve):
var content = await readFile('file.txt');
A konstrukció még nem végleges, de már több transpiler (pl 6to5, regenerator) is támogatja, túl sok minden már nem fog változni.
Ezt nem visszafele kompatibilis módon kell megcsinálni, hanem eleve így kellett volna, 2009-ben.
Most úgy működik a node, hogy IO esetén elindul a "blokkoló" folyamat, az adott kontextust eldobja a rendszer, és a végén a kapott értékekkel meghív egy callback-et.
Úgy lett volna jó, ha a "blokkoló" folyamat előtt elmentik az adott kontextust (memóriaállapotot), elindítják az IO-t, a végén meghívják motoron belül a callback-et, ami visszaállítja a kontextust, és feltölti a változókat. Így lenne pszeudo-szinkron bármely IO függvény, megmaradna a belső eseményvezérlés, és így térne át ma már mindenki js-re.
A visszafele kompatibilitás azért fontos, mert egy meghatározott nyelvről van szó. A nyelvnek ismerjük a tulajdonságait, ezért arra számítunk, hogy úgy viselkedik, ahogy máshol is. Ha nem úgy működik, akkor az egy másik nyelv. És nem véletlen lett pont a JavaScript választva nyelvként a Node-hoz. Azért mert hozza azokat a szolgáltatásokat, mint a callback-ek, closure-ok, aszinkron programozás.
Ha nem akartak volna visszafele kompatibilisak lenni, akkor másik nyelvet használtak volna, mondjuk Go vagy C#, vagy pedig írhattak volna egy teljesen új nyelvet. Egyesek meg is tették, és V8 és JavaScript helyett Lua-t használnak.
De léteznek még más, Node.js-hez hasonló próbálkozások, mint a Vert.x, ami JVM alapon viszont nyelvektől függetlenül hoz egy Node.js-hez hasonló architektúrát, jelenleg Java, JavaScript, Ruby, Python, Groovy, Clojure, Scala és Ceylon támogatással.
Ennek az egésznek semmi köze a visszafele kompatibilitáshoz. Amikor meghívsz egy függvényt, pl. new Date().getTime(), akkor nem tudod, és nem is érdekel, hogy a háttérben mi és hogyan történik, számodra csak az érték a fontos. Ugyanez igaz egy fájl beolvasásánál is: mi a tartalma, vagy ha valamiért nem sikerült, mi a hibaüzenet. Az, hogy a V8 belül eseményvezérelt, egy járulékos komplexitás, magyarul incidental complexity, amit nem kéne a programozó felé kiexportálni, mert nem hordoz számára információt.
A C esetében ilyen incidental complexity a memóriamenedzsment, újabb nyelvekben ezt felváltotta a hulladékgazdálkodás, és már nem kell vele foglalkoznunk. Node.js esetében visszatértünk a gyökerekhez, ráterheltek egy belső rendszerjellemzőt a programozói közösségre, aminek az a következménye, hogy még ebben a node.js megjelenésétől számítva öt évvel későbbi előadásban is a pyramid of doom a központi probléma.
Senkit nem érdekel, hogy a readfile() az belül szinkron vagy aszinkron. Tehát nyugodtan mondhatták volna, hogy a readfile() és társai pszeudo szinkron (belül aszinkron) függvények, mert megtehették volna.
Ehelyett mit csináltak? Valahol olvastam, hogy 28 féle megoldás van a callback hellre, más nyelveket hoztak létre (coffee és társaik), ráadásul már szabványt is módosítanak miatta. Emellett ott van az npm, egymilliom modullal, amiben n-féleképp oldották meg ezt a problémát, nehezítve a karbantartást, fejlesztést, megértést.
Többek között azért kell szabvány, és nyelvi elem hozzá, hogy ha az egyszeri programozó is szeretne valami erőforrásigényes műveletet megvalósítani (netán ezeknek egy láncolatát végrehajtani), amit célszerű lehet aszinkron módon megoldani, akkor legyen rá egy bevett nyelvi formula, és ne kelljen azon siránkozniuk egyeseknek, hogy ahány ház, annyi féle képpen valósították meg az aszinkron művelet kezelését, valamint még a futtatókörnyezet gyártóira sem kell várni, hogy esetleg megvalósítsák az igényelt funkciót "pszeudó blokkoló" módon (mert ugye nem szeretünk általunk kevéssé befolyásolható felekre várni).
Így kapunk egy újrahasznosítható mintát, amit igényeink szerint másolhatunk, használhatunk tetszőleges JS környezetben. Úgy hallottam valakitől ebben a szálban, hogy ez jó dolog.
És mire van inkább szükség, hogy aszinkron vagy szinkron műveleteket végezzünk? Egy kép méretezése mehet aszinkron vagy párhuzamosan az aktuális szállal, de egy adatbázisból azért kérdezek le valamit, mert szükségem van az eredményére most azonnal.
Tehát még egyszer kérdem: miért terheljük rá a programozókra az eseményvezérlés komplexitását (és ebből következően a callback hellt vagy a szabványmódosítást), amikor csak elhanyagolható számban lehetne kihasználni? Úgy hallottam valakitől ebben a szálban, hogy célszerű olyan megközelítést választani, ami több használati esetet old meg.
A nyelvi elemekkel megtámogatott aszinkron lehetőségek több esetet fednek le, mintha a futtatókörnyezet döntené el helyettem, hogy az adott hívás blokkol-e, és ha igen, akkor milyen módon (ne adj isten, csak blokkoló hívások lennének). Ha a nyelvben jelezve van, hogy egy hívás milyen módon fut, akkor tudok számolni a következményeivel. Ha nincs, akkor csak reménykedhetem, hogy nem változnak meg bizonyos változóim értékei, mert a futtatókörnyezet esetleg úgy döntött, hogy csak úgy tesz, mintha blokkolna a hívás, de igazából nem.
Valamint ha ezt a döntést a környezetre bízzuk, ahogy javaslod, akkor oda a hordozhatóság. Hacsak nem vezetjük be a szabványba, hogy hogyan kell megvalósítania a környezetnek, de akkor végülis ugyanott vagyunk a szabványosítás terén, csak az egyik esetben kifejezőbb lesz a nyelv, a másikban pedig leszűkítettük magunkat egy esetre.
Persze az lenne a legjobb, ha mindenttudó lények fejlesztenék ki a programozási nyelveket, és akkor lehetne mindent az elejétől fogva jól csinálni. De ez nem opció, így marad a tapasztalatok alapján történő szabványkovácsolás.
És mire van inkább szükség, hogy aszinkron vagy szinkron műveleteket végezzünk?
Mikor mire. Ezért kell jelölni, hogy melyik hívás aszinkron, és melyik nem.
Mik az aszinkron hívás következményei? Miért kéne megváltozniuk bizonyos változód értékeinek? Tehetnek-e a szoftverkörnyezet (V8) programozói arról, hogy ezek biztosan ne változzanak meg?
Mi köze az egésznek a hordozhatósághoz és a szabványhoz? Mi köze van a szabványnak ahhoz, hogy egy rendszerfüggvény (esetünkben file_read()) hívása aszinkron vagy pszeudo-szinkron módon történik? Hol van leírva a szabványban, hogy függvények nem működhetnek pszeudo-szinkron módon? Miért nem tekinthetünk a file_read()-re úgy, mintha egy ugyanolyan művelet történne, mint egy egyszerű összeadásnál? Miért kell ezt a belső komplexitást kiexportálni, amikor az esetek 99,99%-ában a programozónak nincs rá szüksége? Ha viszont ezt kiexportálták, miért nem tettek bele kézi memóriamenedzsmentet, hogy még kifejezőbb legyen a nyelv? Miért csak 2009 után jött be a blokkolástól való félelem, előtte miért nem volt ilyen?
Egy hosszabb műveletet, mint például a képméretezés, szerintem amúgy sem aszinkron oldanál meg, hisz az adott szál válaszát blokkolná (hehe).
Persze az lenne a legjobb, ha mindenttudó lények fejlesztenék ki a programozási nyelveket, és akkor lehetne mindent az elejétől fogva jól csinálni. De ez nem opció, így marad a tapasztalatok alapján történő szabványkovácsolás.
Itt nem volt semmiféle programozási nyelv fejlesztésről, csak kitalálták, hogy használjanak egy meglévő eszközt kódfuttatásra szerveroldalon. Olvasd el a wikipédiát, hogy mi adta az ötletet a node.js létrehozásához! Nem lehet, hogy rossz eszközt választottak, vagy nem fordítottak elég figyelmet a megvalósításra?
Miért kéne megváltozniuk bizonyos változód értékeinek?
Pont az a baj, hogy nem kéne!
Szinkron végrehajtáskor garanciát kapsz rá, hogy más nem nyúl a változóidhoz, amíg nálad van a vezérlés.
Tehetnek-e a szoftverkörnyezet (V8) programozói arról, hogy ezek biztosan ne változzanak meg?
Mondhatnák azt, hogy oké, akkor amíg valami vár, addig más nem férhet hozzá a scope-hoz. Viszont akkor meg azok a programok törnek el, amik arra hagyatkoznak, hogy ők márpedig hozzáférnek.
Mi köze az egésznek a hordozhatósághoz és a szabványhoz?
Elvárom, hogy a kódom tetszőleges futtatókörnyezetben ugyanazt az eredményt adja (ie6, chrome 283, node, iojs, stb)
Miért nem tekinthetünk a file_read()-re úgy, mintha egy ugyanolyan művelet történne, mint egy egyszerű összeadásnál?
Tegyük fel, hogy az összeadás nem blokkol:
var a = 1;
el1.onclick = function () { a++; };
el2.onclick = function () { console.log(a+a+a); };
Mi itt az elvárt eredmény? A józan paraszti ész azt mondja, hogy 3, 6, 9, stb. Azonban ha az összeadás nem blokkol, akkor simán elképzelhető, hogy a az első összeadás után ((a+a)+a) megváltozik (és pl 4 lesz az eredmény). Ez baj. Ha az el1.onclick nem fér hozzá a-hoz, akkor meg az a baj. Ezt nem tudod feloldani transzparens módon.
Ha viszont ezt kiexportálták, miért nem tettek bele kézi memóriamenedzsmentet, hogy még kifejezőbb legyen a nyelv?
A JS magasszintű nyelv, miért kéne foglalkoznom a memóriamenedzsmenttel?
Miért csak 2009 után jött be a blokkolástól való félelem, előtte miért nem volt ilyen?
Meglepő módon a számítástechnika fejlődik, szükség volt a jobban skálázódó megoldásokra, és az aszinkron i/o elég jól működik a jelek szerint. Amúgy miért csak 1890 után jött létre a lyukkártya, előtte miért nem volt ilyen?
Egy hosszabb műveletet, mint például a képméretezés, szerintem amúgy sem aszinkron oldanál meg, hisz az adott szál válaszát blokkolná (hehe).
Mondhatnák azt, hogy oké, akkor amíg valami vár, addig más nem férhet hozzá a scope-hoz. Viszont akkor meg azok a programok törnek el, amik arra hagyatkoznak, hogy ők márpedig hozzáférnek.
De én azt vetettem fel, hogy eleve így kellett volna kezdeni, és akkor most nem lenne miről beszélni.
Elvárom, hogy a kódom tetszőleges futtatókörnyezetben ugyanazt az eredményt adja
A JS-nek nem része a file_read(), az egy kiegészítés, mint ahogy kiegészítés a node.js részéről a szálkezelés is. Emiatt a node.js-re írt kódod csak node.js-en fog futni.
Miért nem tekinthetünk a file_read()-re úgy, mintha egy ugyanolyan művelet történne, mint egy egyszerű összeadásnál?
Azt kérdeztem, hogy miért ne lehetne a file_read() pszeudo-blokkoló (aminek a megvalósítását fentebb leírtam).
A JS magasszintű nyelv, miért kéne foglalkoznom a memóriamenedzsmenttel?
A memóriamenedzsment zavar, de az eseményvezérelt működés nem? Ha úgy vesszük, a PHP is ugyanolyan eseményvezérelt, csak az képes ugyanabban a kontextusban folytatni a futást, ahol az IO elkezdődött.
az aszinkron i/o elég jól működik a jelek szerint
Valószínűleg ezért téma 2009 óta a callback hell felszámolása...
Egy hosszabb műveletet, mint például a képméretezés, szerintem amúgy sem aszinkron oldanál meg, hisz az adott szál válaszát blokkolná (hehe).
Ha a felhasználó elindít a szerverre egy kérést, amiben egy JPG képet kell átméretezni, akkor az lassú művelet lesz. Ha nem másik szálon indítod el, nemcsak az adott kérést tartod fel, hanem az egész node.js szervert.
De én azt vetettem fel, hogy eleve így kellett volna kezdeni, és akkor most nem lenne miről beszélni.
És akkor hogyan néznének ki a programok? Minden egyes értékadás után ellenőrizni kell, hogy tényleg módosult-e az érték? Nonszensz.
A JS-nek nem része a file_read(), az egy kiegészítés, mint ahogy kiegészítés a node.js részéről a szálkezelés is.
Egyrész a node nem ad neked szálkezelést nyelvi szinten, nem terjeszti ki a nyelvet (néhány globális objektumon kívül, amik egyébként shimelhetőek). Másrészt a függvényhívás szemantikája igenis a nyelv része, ugyanúgy működik node-ban és a böngészőben is.
A memóriamenedzsment zavar, de az eseményvezérelt működés nem? Ha úgy vesszük, a PHP is ugyanolyan eseményvezérelt, csak az képes ugyanabban a kontextusban folytatni a futást, ahol az IO elkezdődött.
Persze, PHP-ban is lehet ugyanolyan eseményhurkot csinálni. A szinkron futás nem eseményvezérelt. A rendszer eseményei érdekelnek, a memóriafoglalásai nem.
Valószínűleg ezért téma 2009 óta a callback hell felszámolása.
Már 2013-ban írtam az elérhető megoldásokról, amik ezt a problémát nyelvi szinten megoldják.
Ha a felhasználó elindít a szerverre egy kérést, amiben egy JPG képet kell átméretezni, akkor az lassú művelet lesz. Ha nem másik szálon indítod el, nemcsak az adott kérést tartod fel, hanem az egész node.js szervert.
Igen, CPU-bound feladatoknál valóban érdemes szálakat használni (bár az áteresztőképesség a processzorok számáig tud csak nőni), hogy elkerüljük a konvoj hatást. Háttérszálakat a node is használ, ezek a felhasználó számára aszinkron hívások.
Másrészt a függvényhívás szemantikája igenis a nyelv része, ugyanúgy működik node-ban és a böngészőben is.
És ezzel most mit szerettél volna mondani?
A szinkron futás nem eseményvezérelt.
Ugyanúgy működik a szinkron futás, mint az eseményvezérelt, csak a végük más. Mindkét esetben meghívnak egy (pl. C library) függvényt (pl. fread()), ami a memória megfelelő részébe bemásolja az adatokat. Ez után a PHP vagy a JS motor feltölti a saját változóit, majd PHP (szinkron) esetén visszakerül a futás a korábbi kontextusba, míg JS esetén meghívnak egy callback függvényt.
Már 2013-ban írtam az elérhető megoldásokról
A callback hellel a felhasználó már a node.js kezdőlapján találkozik, annyira a rendszer alapvető problémája. Eleve így nem lett volna szabad elindulni, erre lehetett volna megoldás, amit a Blokk 2-ben írtam.
Még mindig túl sok ellentmondást látok az elképzelésedben...
var a = read('a.txt');
var b = read('b.txt');
Ez most párhuzamosan hajtódna végre szerinted, vagy sorosan? Hogyan oldanád meg a másik verziót (tehát ha ez párhuzamos, akkor hogyan alakítanád soros végrehajtásúra?)
Más. Az elkézelt implicit aszinkron rendszeredben mi lenne itt az elvárt kimenet?
var a = 1;
el1.onclick = function() { console.log(a, read('a.txt'), a); };
el2.onclick = function() { a++; };
Ahol a read valami implicit aszinkron függvény (azaz elengedi a vezérlést azon a ponton, majd ha végzett, visszakapja), illetve a read futása közben lefut a második függvény. A read nem látja az a változót. És mi történik akkor, ha a read valami párhuzamosan működő (valahol a threadben írtál már rá példát) függvény (azaz valamivel visszatér), mivel tér vissza?
Ugyanúgy működik a szinkron futás, mint az eseményvezérelt, csak a végük más. Mindkét esetben meghívnak egy (pl. C library) függvényt
Nem. Előbbinél egy blokkoló rendszerhívás történik, utóbbinál aszinkron (oké, ez node esetében nem teljesen igaz, de ha a hálózati kommunikációról beszélünk, akkor igen).
A callback hellel a felhasználó már a node.js kezdőlapján találkozik, annyira a rendszer alapvető problémája.
var a = read('a.txt'); var b = read('b.txt'); szinkron_fuggveny();
Az első sorra érkezik a vezérlés, a háttérben elindul az a.txt beolvasása. A második sorra érkezik a vezérlés, párhuzamosan elindul a b.txt beolvasása. A harmadik sorra érkezik a vezérlés, szinkron függvény a következő, ekkor megvárja a rendszer a két fájl beolvasását, és utána futtatja.
A console.log(a, read('a.txt'), a); ekvivalens a következővel:
var belso_valtozo = read('a.txt'); console.log(a, belso_valtozo, a);
Tegyük fel, hogy az a.txt beolvasása tíz másodperc, ha közben rákattintanak az el2-re, akkor az a++ utasítás szinkron, azaz a rendszer csak akkor hajtja végre, amikor az a.txt-t beolvasta.
Mint a 22-es hozzászólásban írtam, az egész pszeudo-szinkron dolognak szerveroldalon látom értelmét, így a fenti onclick-es kérdésed szerintem indifferens.
Értjük, de a probléma azóta már meg lett oldva.
Ha meg lenne oldva, akkor nem született volna meg a videó.
És ki tudja megfejteni, és miből, hogy a program így működik? Mármint mi jelöli, hogy a read függvényed után a következő azonnal végrehajtódik.
var a = read('a.txt');
var b = read('b.txt') + a;
var c = b + read('c.txt')
A fenti kódot hogy kellene értelmezni? Miért úgy? Ki tudja, hogy úgy fut le. Hogy lehet jelölni egy saját függvényen, hogy ez párhuzamosan futhat? Vagy hogy nem futhat?
function a(filename) {
return read(filename + '.txt');
}
console.log(a('a'), a('b'));
És ki tudja megfejteni, és miből, hogy a program így működik? Mármint mi jelöli, hogy a read függvényed után a következő azonnal végrehajtódik.
Miért érdekes számodra ez az információ?
Egy saját függvény vagy metódus akkor lesz pszeudo-szinkron, ha van benne pszeudo-szinkron függvényhívás.
A fenti kód nagyjából ekvivalens a következővel (Bence cikke alapján):
job(function () { try { var a = yield promisify(read)('a.txt'); var b = yield promisify(read)('b.txt'); var c = b.toString() + yield promisify(read)('c.txt'); cache(e) { ... } });
Pszeudo-szinkron feldolgozás mellett a következők kerülnének a konzolba, a sor eleji szám az eltelt idő az első sor lefutása óta. Tegyük fel, hogy az a.txt 5080ms, a b.txt 5000ms, a c.txt 6200ms alatt érkezik le:
Lényegében ezt írtam én is másodikként, de a kódból nem ez látszik, hanem amit első példa kimenetnek írtam. Így pedig nem egyértelmű a kód. Ezért érdekes az az információ, hogy milyen módon hajtódik végre egy adott függvény.
Akkor lesz a kimenet a második eset szerint. Annyi a bónusz, hogy ha ránézek a kódra, akkor el tudom dönteni, hogy mi lesz a kimenet, mert jelölve van, hogy aszinkron a hívás. Míg ha csak "megpiszkálják kicsit a motort", és random függvények pszeudo blokkolnak, akkor a program hamar inkonzisztens (vagy legalábbis a kódból nem egyértelműen következő) állapotba kerül.
Miért egy kliensoldali problémát hozol egy szerveroldali szálban? Tudsz hasonló problémát vázolni szerveroldalon? Szerveren hol van jelentősége az időnek a timeouton kívül?
Ezt nem értem, mire volt válasz. Mi volt a kliens oldali probléma? Miért ne lenne jelentősége szerveroldalon az időnek? Ott is minél előbb el akarjuk végezni a műveleteket, és visszaadni a vezérlést az operációs rendszernek.
Teljesen máshogy működik a kliens- és a szerveroldal. A kliensen van szerepe az időnek, mert nem folyamatosan történnek a dolgok, hanem az egyes műveletek között eltelik bizonyos idő, pl. rákattintok erre az elemre, frissül valami, gondolkodok, kimegyek kávézni, visszajövök, rákattintok a másikra stb.
Szerveroldalon, ezzel szemben, ha jön egy kérés, akkor elvégzem a műveletet, összeállítom a választ, majd kiküldöm a kliensnek. Tehát a kérés beérkeztétől a válasz kiküldéséig folyamatosan dolgozik a gép, és ebbe beleszámít az is, hogy vár például az adatbázisra, hisz addig nem mehet ki semmi, amíg nem kapott eredményt. Az időfaktornak csak akkor van szerepe, ha egy IO kérésre a megadott elfogadható timeout-on belül nem érkezik semmi.
A Bence által vázolt példában az időzítő egy olyan eszköz, aminek a fentiek miatt csak kliensoldalon van értelme és szerepe, szerveroldalon nincs. Ezért kértem tőle szerveroldali példát, ahol információt hordoz az, hogy egy függvény szinkron vagy pszeudo-szinkron módon fut.
Akkor valamit nem látunk azonosan szerver oldalon. Számomra szerver oldalon rengeteg bejövő adat van, és nem csak a kliensek oldaláról. Hanem vannak másik szerverek, amik kommunikálnak az enyémmel, adatokat küldenek be folyamatosan, vagy az én szerverm kér adatokat másik szerverektől, amiket fel kell dolgozni, el kell menteni, vagy tovább kell küldeni egy másik szervernek. A szerver oldalon a frontend szerver csak egy lépcsőfok. Sokszor vannak mögötte más szerverek is.
Értem, amit írsz, csak azt nem, hogy hogy jön ez ide. Engem mint felhasználót hol érdekel, hogy te a háttérben hány forrásból szerzed az adatokat? Amikor rákattintok egy linkre, akkor azt várom, hogy bejöjjön egy weboldal vagy szolgáltatás. Hogy hogyan fésülöd össze a forrásaidat, attól nem leszek okosabb.
Az a probléma, hogy te úgy tekintesz a szerver oldalra, mintha az csak egy HTTP szerver lenne, ami fájlokat szolgál ki. Pedig a kép ennél sokkal összetettebb.
Szerveroldalon, ezzel szemben, ha jön egy kérés, akkor elvégzem a műveletet, összeállítom a választ, majd kiküldöm a kliensnek.
Ha jön egy kérés, elindul egy szálon a feldolgozás és ugyanazon fejeződik is be. Mi köze van ennek ahhoz, hogy még honnan halászgat össze adatokat valamelyik másik futó folyamat?
Én arról az atomi kérésről beszélek, ami a kliensről bejön, és amire választ is kell küldenem. Ezen az atomi egységen belül hol van szerepe az időnek?
Te abból indulsz ki, hogy szerver oldalon csak PHP mehet, ha jól értelek.
Mondjuk egy netbank felületén lekéri valaki az egyenleget.
Csak és kizárólag az egyenleg összegét kéred le valami AJAX-os eszközzel.
Szerinted mi fog történni szerver oldalon? Megsúgom: nem egy SELECT fut, ami kikapja az adatbázisból a számla aktuális egyenlegét...
7-8 éve mondta egy ismerősöm, hogy az akkori netbankjuknál minden kérés belül nagyjából húsz szerveren ment keresztül. Abból indulok ki, hogy egy kéréshez egy kapcsolatot használunk, amin sorosan mennek ki az adatok, legyen az HTTP kérés, vagy akár egy stream. A lényeg, hogy a kiszolgálón lévő szoftver indíthat akárhány párhuzamos olvasást, például élőben keveri rá a hangot a videóra, az szigorúan sorosan mehet ki.
Tehát nem fordulhat elő az, hogy a kimenetbe rossz sorrendben kerül a bájtfolyam, erről a programozónak kell gondoskodnia. Ha pedig így van, akkor továbbra sem értem, milyen plusz információt hordoz az, hogy egy függvényt generátorokkal írok meg, ahhoz képest, mintha minden IO-t végző függvény automatikusan pszeudo-szinkron lenne.
"Szerveren hol van jelentősége az időnek a timeouton kívül?"
"Az a probléma, hogy te úgy tekintesz a szerver oldalra, mintha az csak egy HTTP szerver lenne, ami fájlokat szolgál ki. Pedig a kép ennél sokkal összetettebb."
Én itt léptem be.
Ennek mi köze ahhoz amit most rajtam próbálsz számon kérni?
(off: fura... számonkérés egy szó, de számon kérni kettő???)
Kétféle IO művelet van:
1, folyamatos, például egy fájl beolvasása vagy adatbázis-lekérdezés; ilyenkor lehet és van értelme használni pszeudo-szinkron függvényeket
2, időben változó, például websocket, amin véletlenszerűen jönnek az adatcsomagok, ilyenkor jobb híján marad a callback-es vagy ekvivalens megoldás
Ismét az a legfontosabb kérdés, hogy az esetek túlnyomó többségében miből van több, az előbbiből vagy az utóbbiból.
Ismét az a legfontosabb kérdés, hogy az esetek túlnyomó többségében miből van több, az előbbiből vagy az utóbbiból.
Az én kódjaimban inkább utóbbiból, azaz folyamatosan van rengeteg stream, amiből adatot olvasok. Ezek fájlok, HTTP lekérések, és olvasások adatbázisból. Mindegyik stream-ként jelenik meg számomra, leginkább azért így folyamatosan fel tudom dolgozni a bejövő adatokat, nem kell várnom, hogy megjöjjön a vége (főleg mivel rengeteg memóriát megenne, ha megvárnám).
Remélem, hogy igen. Elvégre, ha valaki kezébe kerül egy olyan eszköz, amit kifejezetten ilyen feladatokra optimalizáltak, akkor remélhetőleg ki is használják. Ha nem akarnák kihasználni, akkor rengeteg mást választhatnak.
Ezt roppant egyszerűen oldanám meg: elindítok n darab pszeudo-szinkron lekérést, amik párhuzamosan futnak, és a következő szinkron parancs futtatása előtt addig várnék a válaszokra, amíg mind be nem érkezik.
var valtozo1 = pszeudo('http://bolt1.hu/api?keres'); //a következő parancs is belül aszinkron, azaz párhuzamosan indítjuk az elsővel var valtozo2 = pszeudo('http://bolt2.hu/api?keres'); var valtozo3 = pszeudo('http://bolt3.hu/api?keres');
//random szinkron parancs, addig várunk, amíg mind meg nem érkezik az összes válasz i++;
Az első kérdést nem értem. A másodikra pedig a válasz, hogy például egy pszeudo-szinkron függvény által visszaadott választ egy változóba teszünk, akkor ezt a változót zároljuk, és csak akkor engedjük olvasni, amikor a függvény lefutott. Ez után egy pszeudo-szinkron függvénnyel küldhetjük is ki.
var valtozo1 = pszeudo_olvas('api1?keres'); var valtozo2 = pszeudo_olvas('api2?keres');
pszeudo_kuld(valtozo1); //addig vár, amíg a valtozo1 felszabadul pszeudo_kuld(valtozo2);
//random szinkron parancs, azután jut ide a futás, miután kiküldtük mindkét változó tartalmát i++;
10db pszeudo_olvas kérést kell lefuttatnom összesen, de azt szeretném, hogy 5nél több ne fusson párhuzamosan egyszerre.
Tehát van egy 10 hosszú sorom, amiből egyszerre max 5-öt tudok feldolgozni.
Megjegyzés:
mennyire olvasható az a kód, ami formailag nem tesz különbséget pszeudo szinkron függvények, változók és szinkron társaik között. Vagy ha különbséget is tesz, mennyire olvasható a végeredmény, melyben az aszinkron és szinkron blokkok ugyanúgy néznek ki?
Az első kérdésre így a válaszom: pontosan ugyanúgy, ahogy most is megoldod.
Megjegyzésedhez: A kód ugyanúgy nézne ki flow szempontjából, mint egy php kód. Nem jut eszembe olyan eset, amikor pszeudo-szinkron függvények mellett valódi aszinkron hívásra lenne szükség callback-es megoldással.
első kérdés:
tehát a http kérés végén egy callback-ben ellenőrzöm, hogy van-e a sorban még elem és ha van elkezdem futtatni? értem :D
megjegyzés. bocsánat, rosszul fogalmaztam. mennyire olvasható az a kód amelyben a pszeudo-szinkron (de aszinkron futó) folyamatok és a ténylegesen szinkron futó részek ugyanúgy néznek ki?
Kérdésedre: Pl. meghívod a wait_until_all_asynchronous_calls_finished() függvényt.
Megjegyzésedhez: Miért fontos számodra tudni, azaz mit kezdesz azzal az információval, hogy a rendszer a háttérben szinkron vagy pszeudo-szinkron módon tölti fel a változód egy függvényhívásnál?
kérdés
minek hívjam meg a függvényt, ha a következő szinkron hívás alapból meghívja?
szóval hogyan garantálom, hogy 5-nél több ne fusson, mert ezt még mindig nem tudom.
megjegyzés
performancika (persze a mai világban minden olyan gyors, hogy nem számít). szóval írok egy kódot, megtervezem, hogy ezek a részek fussanak szépen párhuzamosan ha van rá mód, aztán jön pistike beszúr egy szinkron kérést, a példánál maradva mondjuk a http kérést indító és a választ feldolgozó függvények közé, és hopp, nem úgy működik ahogy kellene és fogalmunk sincs miért.
Kérdésedre: Azért kell meghívni a fenti függvényt, hogy garantálhasd a maximum öt párhuzamos hívást. Nem egyszerűbb, mint a callback hellel szerencsétlenkedni, és évekig várni az ES7-re?
Megjegyzésedre: kommentelj vagy gondolkodj egy kicsit, mit lehet kihozni az adott körülményekből. Aszinkron hívások mellett is lehet hülyeségeket csinálni, hogy megakaszd az egész szerver futását.
Végül pedig a pszeudo-szinkron függvények léte nem zárja ki, hogy mellettük ott legyenek a hagyományos, aszinkron változataik. Probléma megoldva.
kérdés:
de ha 5 pszeudo-szinkron kérés után rakok egy wait_until... akkor lesz, hogy 4,3,2,1 fut csak egyszerre, de én azt szeretném hogy mindig fusson 5, amíg van feldolgozatlan kérés. lásd Poetro hozzászólását.
callback-es esetben nem igazán értem, hogy hogyan lehet a következő sorban megakasztani a dolgokat véletlenül. elindult a folyamat, le fog futni.
azt értem, hogy a pszeudo szinkron függvények léte nem zárja ki az aszinkron függvények létezését, csak azt nem értem, hogy akkor az aszinkron hívások elfedésére miért hoztuk létre a pszeudo szinkron függvényeket, hiszen azok "teljesen egyenértékűek". ja bocs mégsem. értem.
Dehogy érted. Nem mindegy, hogy van mondjuk a jelenlegi helyzet, amikor
1, minden aszinkron, és jön vele a callback hell, és eltelik bő fél évtized, mire megoldást találnak a problémára (mert a programozók már csak olyan esendők, hogy a soros végrehajtást tudják hatékonyan leprogramozni),
vagy
2, minden pszeudo-szinkron, ami mellett lehetőséget adunk a renitenseknek arra, hogy futassák aszinkron, amit az úri kedvük szeretne.
Már unalmas ez a jössz mindig a callback hellel, amikor már jó ideje vannak rá megoldások: promise-ok és generátorok. Elérhetőek most, azonnal, szerver ÉS kliensoldalon. Mielőtt jönne a kérdés hogy hogyan: iojs/0.11 + 6to5
Szerintem nagyon sokan örülnének itt ha utána néznél dolgoknak mielőtt repetitíven mindig ugyanazt mondogatod...de a callback hell de a callback hell.
Látom, tájékozott vagy a témában, úgyhogy lenne két kérdésem, csak hogy a jövőben ne állítsak sületlenségeket:
1, mekkora az io.js elterjedtsége a teljes node.js spektrumban?
2, az npmjs.com-on lévő jelenleg kb. 120 000 csomagból hányban használják ki ezt a lehetőséget?
A Node.js 0.11 is támogatja és tudtommal a Koa.js a legnépszerűbb, ami erre épít. De ha komolyan érdekel a téma, akkor egy kis kutatással megtudod a második kérdésedre a pontos választ.
Például co nevű generátor alapú aszinkron könyvtárra közel 300 modul támaszkodik.
Nem arrol van szo hogy a packageknel hogy van elterjedve, hanem hogy te ha nekiallsz egy alkalmazast lefejleszteni tudod e hasznalni
A librarykben ugy is es5 kompatibilis kodnak kell lennie hogy mindenki tudja hasznalni...viszont a Promiseok ott is elerhetoek mar library formajaban.
De, ez nagyon fontos kritérium. Ha használok egy csomagot, akkor
1, Értenem kell a kódját, hogy ha hiba van, tudjam, mi okozta. Ha tele van callback-ekkel, vagy pyramid of doom, akkor nem fogom megérteni.
2, Ugyanígy problémát okozhat a karbantartás is, mert egy nagyobb modul kódját nem feltétlenül fognak átírni a szerzői az újabb elvek szerint, és előbb-utóbb megy a kukába.
Ahol mar a forraskodjat kell bogarasznom ott mar baj van: vagy a doksi hianyos vagy hibas a mukodes. Ha nincs ilyen csak a mukodeset kell ertened nem a kodjat.
Ez nem valtoztat azon h a sajat kododnal tudod hasznalni mar ma
Nem tudom mennyire vagytok ismerősek ruby ökoszisztémával de ők ezeket a "hogy nézzen ki az API" köröket már pár éve lefutották saját kis köreikben, lehet tőlük meríteni.
Anno 1.9-es ruby verzióval megjelentek Fiber-ek a nyelvben (ezek pehelysúlyú konkurenciát támogató elemek) és az akkor már relatíve elterjedt EventMachine nevű reactor-pattern libhez elkészült az EM-Synchrony kiterjesztés.
Ez a már emlegetett "callback-hell"-re ad megoldást, olvasmány: Untangling Evented Code with Ruby Fibers.
Az eredmény kódban valahogy így néz ki (példák fenti linkről):
EventMachine.synchrony do
page = EventMachine::HttpRequest.new("http://www.google.com").get
p "No callbacks! Fetched page: #{page}"
EventMachine.stop
end
Vagy ha több requestet akarsz futtatni akkor valahogy így:
EventMachine.synchrony do
multi = EventMachine::Synchrony::Multi.new
multi.add :a, EventMachine::HttpRequest.new("http://www.postrank.com").aget
multi.add :b, EventMachine::HttpRequest.new("http://www.postrank.com").apost
res = multi.perform
p "Look ma, no callbacks, and parallel HTTP requests!"
p res
EventMachine.stop
end
Ez persze önmagában mind szép és jó, de ahhoz, hogy mindebből valami olyan kód legyen amihez lehet HTTP-n beszélni még kell egy webszerver (thin, goliath) ami támogat minket ebben, illetve framework support is jól jöhet. Példaként álljon itt a synatra nevű microframework fiberekre felkészített verziója: Sinatra::Synchrony, ezt a diasort is érdemes átfutni.
További kutatásra ajánlom az eventmachineról szóló előadásokat itt: confreaks.
A dolog fő hátulütője persze az, hogy fiber/eventmachine-re felkészített driverekre van szükséged mindenre amit ezekben a szinkronizációs blokkokban akarsz csinálni párhuzamosan, mint DB (legyen az sql vagy nosql) lekérdezések, HTTP requestek és így tovább. Ruby közösség egy sor ilyet írt népszerűbb dolgokhoz, és nekem úgy tűnik ez a fajta "aranyláz" nemsoká megindul majd JS világban is csak "generator-aware" lesz a buzzword "fiber-aware" helyett.
Fibers elérhető node-hoz is, de nem nagyon lett felkapva (én sem kedvelem). A generátorok/async függvények előnye, hogy nincs szükség különösebb átalakításokra: a meglévő callback API mechanikusan alakítható át Promise alapúvá.
Blokk
Be: továbbra sem értem a "blokkolástól" való mániákus félelmet (kliensoldalon). A videó példájával élve, amikor lekérem a hálózatról egy adott cég részvényeinek az árfolyamát, akkor ha ezt szinkron csinálom, a felhasználó hiába csinál bármit, amíg meg nem jön a válasz, nem válaszol a böngésző.
Két eset lehetséges:
1, Gyors a hálózat esetén ez nem számít, mert hamar megvan az eredmény, mire a következő elemre viszi az egerét, már frissítettük az adatokat.
2, Lassú hálózat esetén ha a következő funkciókra kattint például, akkor mindegyik helyén ott fog pörögni a töltést jelző animáció egymás után, hisz mindegyikre (nagy valószínűséggel) lassú lesz a válasz.
Ráadásul hiába indítjuk párhuzamosan a kéréseket, ha a szerveroldalon azok a felhasználó munkamenetéhez férnek hozzá, ott elsődleges fontosságú a konzisztencia, azaz ha az első kérés egy változót ír, akkor zárolni kell a munkamenetet a kérés befejeztéig, a második kérésnek meg kell várnia ezt, és csak akkor lehet elkezdeni feldolgozni.
Márpedig – webes alkalmazás esetén – előbb-utóbb, de inkább előbb olyan funkcióba fog botlani a felhasználó, ahol szükség van a netre. Értem én, hogy a felhasználói élmény az rendkívül fontos, node a sok pörgő animáció nem pont ekvivalens az úgynevezett blokkolással?
Szerintem
Bár már számtalanszor
1) A hálózat válaszidejére nincs garantált felső korlát. Ha 100ms felett van a válaszidő (ami a hálózat késleltetése + kiszolgálás ideje), akkor azt a felhasználó észreveszi.
2) Blokkolás esetén semmi nem fog pörögni, a böngésző újrarajzolni sem tudja a képernyőt (az egész alkalmazás lefagy).
Nem azért használunk aszinkron kéréseket, hogy párhuzamosan többet is tudjunk futtatni, hanem azért, hogy az alkalmazás reszponzív maradjon.
1, Mi van akkor, ha
Az XMLHttpRequest objektumnak van timeout tulajdonsága.
2, Most próbáltam ki, Firefox 35 és Opera 12 alatt folytatódnak az animációk, Chrome 24 alatt nem (feltételezem, hogy újabbak alatt igen) – az animációk rajzolásának egyébként sem kéne közük legyen a JS-hez.
<style>
#animacio {
width: 16px;
height: 16px;
}
</style>
<body>
<div id="animacio"></div>
<button id="gomb">Gomb</button>
<script>
function tolt() {
animacio.style.backgroundImage = 'url(\'ajax-loader.gif\')';
var xhr = new XMLHttpRequest();
xhr.open("GET", 'lassu.php', false);
xhr.send(null);
animacio.style.backgroundImage = 'none';
}
var animacio = document.getElementById('animacio');
var gomb = document.getElementById('gomb');
gomb.onclick = tolt;
</script>
</body>
</html>
timeout
Például beállítok egy rövid timeoutot, amin túllóg a szerver válaszideje. Ha mégis végrehajtódik a szerveroldalon a művelet, és válaszolna, akkor a szerver válasza elvész, vagy mégis jöhet egy hívás egy callbackre?
Na jó, ez így zavaros, már olyan rég használtam szinkront ilyen esetben, hogy elsőre elfelejtettem, hogy nincs is callback. De éppen lehetne, timeout után. Vagy a timeout esetén hívódhatna meg egy callback, ami vagy lezárná a hívást, vagy tovább várna, aszerint, amit akarunk.
Na mindegy, összességében nem túl nagy lenne a nyereség, maradok az aszinkronnál, már hozzászoktam.
Szerintem pontosan ugyanaz
1, Mi van akkor, ha
És mi van akkor, ha a következő használandó funkció nem fordul a hálózathoz? Nézze tétlenül a gif animációkat, mert azok legalább működnek? Szerintem inkább keres egy másik alkalmazást, ami reszponzív (ha nincs monopol helyzet; ha az van, akkor csak gondol arra, hogy lecserélné).
Én például szeretem az olyan webmail klienst, ahol miután "elküldtem" egy levelet, egyből olvashatom a korábban letöltött másik/következő levelet, vagy elkezdhetem írni rá a választ, vagy új levelet, használva az esetleg JS-t is hasznosító szerkesztőfelületet.
Felteszel sok "mi van, ha?" kérdést, és csak azokat az opciókat veszed figyelembe, amik a te álláspontodat látszanak igazolni. De minden "mi van, ha?" mellet ott van egy "mi van, ha nem?" kérdés is. Jelen esetben a te javaslatod, míg az első esetet látszólag szebben megoldja, a másikra egyáltalán nem nyújt megoldást. Én inkább azt a megközelítést választanám, ami több használati esetet megold, mert ha csak kalapácsom van, akkor csak kalapálni tudok, míg ha egy összetettebb szerszámom, akkor mást is (ehhez persze meg kell tanulni a szerszám használatát, de valamit valamiért).
Erről a Firefox ezt gondolja:
De még ha használható is lenne a timeout, az milyen felhasználói élmény, hogy ha 30 másodperc helyett 31 alatt érkezne meg a válasz, akkor dobjuk el az egészet, hogy várnom kelljen még egyszer 30 másodpercet semmittevéssel töltve, reménykedve, hogy a megengedett idő alatt ezúttal megjön a válasz, ahelyett, hogy teszem a dolgom az első 31 másodperc alatt, és kapok értesítést, hogy folytathatom azt a szálat, ami esetleg függöt tőle? Szerintem olyan, amit gondolkodás nélkül lecserélek.
Tehát örüljek annak, hogy mennek a gif animációk és esetleg tudok görgetni, de ha bármi mást szeretnék csinálni, ami JS alapú, akkor ne is álmodjak róla, mert annak úgysincs értelme, mert hátha a hálózatra vagy egyéb szekvenciális függőségre lenne hozzá szükség?
Szerintem ezt ne a nyelv/futtatókörnyezet döntse el, hanem az aktuális alkalmazás az üzleti logika alapján. Igen, ehhez az üzleti logikát szükséges a gép nyelvére lefordítani, de mintha ez lenne a munkánk.
Továbbá ismét a Firefox konzol üzenetét idézném, amit szinkron XHR hívás esetén ír:
Ennek a lónak is van egy másik oldala, ahova ha átesünk, akkor szintén a kőkorszakban maradunk.
+1
És mi van akkor, ha a
Egy levélküldésnél valószínűleg egyébként nyugodtan használhatsz aszinkron kéréseket, csak ne feledd el, hogy ez egy nagyon primitív funkció. Amint olyan adathalmazzal dolgozol, ahol összefüggéseket kell kezelni (egy helyen átírsz valamit, és a másik helyen is frissíteni kell), pont a fenti eset fog előállni, hogy hiába küldesz el párhuzamosan több kérést, a szerveroldalon csak sorosan tudod kiszolgálni a megosztott memória (munkamenet) miatt.
Egyébként pedig nem az aszinkron hívásokkal van feltétlenül bajom ("továbbra sem értem a "blokkolástól" való mániákus félelmet"), hanem azzal, hogy a szinkron hívást nem használják, pedig bizonyos összetettség felett csak ennek van értelme.
a szerveroldalon csak sorosan
Miért is? Miért lenne korlátozó tényező a megosztott munkamenet? Miért ne lehetne párhuzamosan X+1 szerver ami kiszolgálja a kéréseket, és ugyanazt a munkamenetet használja valamilyen memória adatbázisban (Redis, memcached)?
Konzisztencia
Ennél azért vannak finomabb
A példáddal élve: hiába írod
Nem feltétlenül elküldeni akarom, hanem megírni. Ha blokkol az alkalmazás, akkor amíg az első levél el nem ment, addig írni sem tudok, csak várni. Ha az animációkat is kikapcsolhatóvá akarjuk tenni a környezet védelmében, akkor miért akarjuk tétlenségre kényszeríteni a felhasználókat ahelyett, hogy haladhatnának a dolgukkal, amikor lehet?
És mi van, ha nem olyan adathalmazzal dolgozol?
Az eldobás szempontjából ekvivalens, viszont aszinkron hívás esetén engedem a felhasználót mással foglalkozni, ha tud. Ha nem tud, akkor úgy írom meg az alkalmazást, hogy ne tudjon, jelezve, hogy várnia kell a szerverre. De nem úgy, hogy blokkolom az UI 99%-át.
A szekvenciális végrehajtás mióta egyenértékű a blokkolt felhasználói felülettel/alkalmazással? Vannak remek adatszerkezetek és módszerek, amik biztosítják az egymásutániságot úgy, hogy nem blokkolják a felületet és engedik a lehetséges párhuzamos folyamatok futását.
Nem feltétlenül elküldeni
Ha a böngésző
Pont a két eset nem lehetséges
Azt írod két eset lehetséges, holott pont nem. Vagyis neked igazad van, mert Te az átlagról (hálózat sebességéről) beszélsz. Ha onnan nézem tényleg mindegy, hogy mi van. És igazad is van, ha nem túl nagy a szórás az értékek között.
Sajnos azonban az életben nem így van, mert van bizony olyan, hogy egy-egy kérésre igencsak későn érkezik a válasz. Ezek a késő válaszok pedig szinkron esetén bosszúságot okoznak a felhasználónak, mert a gyors válaszok elkényelmesítették, és nem fogja érteni, hogy ami eddig pikk-pakk az most miért nem, meg mi van, kattintottam héé.
És ezek azok az apró bosszúságok amik a felhasználói élményt lerontják. Ezen tud segíteni az aszinkron kiszolgálás, mert mire észrevennéd, hogy para van, már nincs is.
Az emberi elme meg hekkelhető, mert attól, hogy nincs ott a válasz egészben, de elkezdett megjelenni, azaz érzésed van, hogy történik valami. Ugyan úgy, mint amikor kölcsönadsz 100 forintot valakinek, és ő a határidőre csak 10-et törleszt, aztán a rákövetkező héten megint 10-et és így tovább, sokkal jobban elviseled, mint mikor 10 hét késéssel adja vissza az egész lóvét. Tölts egy fészbúk oldalt, ott is a tényleges tartalom megjelenéséig nagyon sokat kell várnod, holott az az érzésed, hogy pikk-pakk, és képes vagy várni több mint 3 másodpercet. Holott 5 másodperc fehér képernyő után biztos bezárnád a böngésződet, hogy ez nem megy.
pp
Az előadó testi adottságaira tett megjegyzéseid nem valóak egy szakmai oldalra. Ezek ugyanis nem az előadót, hanem téged minősítenek. Kérlek az ilyen megjegyzéseket - ha már a szerkesztők nem figyelnek erre -, hanyagold ezen a szakmainak gondolt oldalon. Köszönöm.
Szerintem az zavart megNem
Félig ki: A facebook-os példád abból a szempontból rossz, hogy ha a teljes HTML-t egyben küldenék le, és nem n darab párhuzamos kérést indítanának, akkor jóval gyorsabban menne például a kezdőlapjuk megjelenítése.
Az előadónak a hanghordozása nem testi adottság, hanem tanult és tanulható tulajdonság. Nagyon zavaró volt végighallgatni így a prezentációt. Ahogy Ádám is minőségibb írásokat kér, ha van alternatíva, inkább azt kérném beküldeni.
Felhasználói élmény
Akkor miért nem így tesznek?
Nem tudom. Talán azért, mert
Tegyük fel, hogy értenek
Akkor valami más tipp?
pp
Például modulokra bontották
Ez nem magyarázat, ez tény.
Szóval fussunk még egy kört.
Miért így csinálják?
pp
Újrafelhasználhatóság?
Mi köze az
Fussunk még egy kört. (akár Te is felteheted magadnak ezeket a kérdéseket, de természetesen én is feltehetem, csak úgy lassabb lesz a gondolkodás)
Miért így csinálják a Facebook-nál?
pp
Passz. Próbálj meg rávezetni,
Én már leírtam, te mondtad,
pp
Én is leírtam, hogy miért
Lehet, hogy leírtad, de én
Írtam egy példát, arra, hogy bár "egy kapcsolaton lecsorgó HTML-t gyorsabb feldolgozni, mint n kapcsolaton lejövő JS-t", mégis van aki használja (nem is kis cég) a felhasználói élmény javítása szempontjából.
Erre írod, hogy rossz a példa, gondoltam azért rossz, mert szerinted nem a felhasználói élményt akarják javítani. Erre kérdeztem rá, hogy akkor szerinted mi a pékért csinálják így, ha nem ezért. Gondoltam tudsz erre választ adni, ezért a sok kérdés.
"nem nagyon látok érvet a facebook megoldása mellett"
És amit én írtam, hogy a felhasználóban azt az érzetet keltsék, hogy valami történik? Az nem lehetséges?
Megnéztem, hogyan működik,
Nem egészen értelek. Egyrészt
Máshol meg ezt:
Ami nagyon sokat dobott az egészen, hogy letöltés közben a böngésző címsorában folyamatosan kijelezte, hány százaléknál tart.
Most akkor az a jó, ha van pörgettyű/folyamatjelzés vagy az, ha befagy az oldal?
Nem ekvivalens a két példa.
A kereskedős példában pedig folyamatosan jön az anyag.
Ki mondta, hogy az aszinkron
Aszinkron hívásnál folyamatosan tudod frissíteni az állapotot. Szinkronnál erre nincs lehetőséged.
Látod, ez egy nagyon jó
Már megoldották
kis munkával járna valamilyen
Mihez képes kis munkával? Ha nem tudjuk mennyi idő múlva jön vissza a tartalom, és nem tudjuk, mekkora a tartalom mérete, és milyen gyors az adatátvitel, nem tudom, honnan tudnánk kis munkával kiszámolni és kijelezni a százalékos értéket, főleg akkor, ha szinkron kérésről van szó.
Ha nem tudod a tartalom
Olvasni
Majd a böngésző olvassa és
Idő
Is - is
Ácsi
Ha itt 2015-ben az aszinkron
Attól, hogy Gábor minden
Egyszerűség
Ez mindig nézőpont
PHP-ban dolgozol, mert ugyanaz a feladat C++-ban sokkal több kódot igényel. A CSS és JavaScript újdonságokat viszont, amik épp azt teszik lehetővé, hogy kevesebb kóddal valósítsunk meg korábban több kódot igénylő dolgokat, meg szükségtelennek tartod, mert nélkülük is elvégezhető a feladat.
Az a baj, hogy a saját szubjektív absztrakciós szinted valamiféle objektív dolognak tartod, és ementén ítélsz meg minden technológiát. Ha már úgyis szereted az egyházi tematikájú metaforákat, inkvizícióval és eretnekekkel, akkor azt kell hogy mondjam, olyan vagy mint a bigott protestáns, aki meg van róla győződve, hogy a katolikus és az ateista is a pokolra jut.
A példád rossz
A HTML, CSS és JS "újítások", "szabványosítás" bevezet egy újabb szintaxist az adott dologra (átnevezés). Vegyük például az AJAX hívást: régi IE-ken a megfelelő ActiveX-et kellett létrehozni, míg más böngészőkön már ott van az XMLHttpRequest objektum. Viszont életemben elég egyszer megírni egy függvényt, ami megvalósít egy funkciót, onnantól kezdve semmi mást nem kell tennem, mint beinclude-olni, és működni fog. A szoftvermásolás egy kvázi ingyenes dolog.
Magyarul pontosan ugyanannyi munkával jár az adott funkció használata bármely környezetben és bármely időpontban, legyen az szabványos vagy sem. Kit érdekel, hogy pár tíz sorral több a kód, és van benne egy detektálós rész, ami pár if-ből áll? Senkit.
Ebből következik, hogy ez az egész "szabványosítás" értelmetlen, és elveszi az időt sokkal fontosabb dolgoktól. Az Irányváltásban sem válaszolt senki arra a felvetésre, hogy az interneten növekvő tartalmi mennyiség feldolgozására nem született technológia. A webhelyek száma megtizenhatszorozódott az utóbbi tíz évben, de nekünk van tizenhatszor annyi időnk látogatóként, hogy ezeket átfésüljük, ha keresünk valamit? Nincs. Tizenhatszor jobb lett a Google? Nem. Akkor miért pazarlunk egy másodpercet is "szabványosításra", ha úgysem nyerünk vele semmit, csak inkompatibilitást?
Ezeken kéne a tisztelt katolikusoknak és ateistáknak elgondolkodni.
A PHP egy adott környezet,
Mi teszi termelékennyé?
Ne vegyük az AJAX hívást. Vegyük például a lekerekített sarkokat. Mennyi CSS, HTML és képfájl kellett hozzá mielőtt egyetlen sorból meg lehetett oldani?
Mert a szoftvert mindenki arról ismeri, hogy elég egyszer megírni, és soha többet nincs vele dolog.
A legkevésbé sem az, ha hálózaton kell utaztasd, parzolnod kell, memóriában kell tartsd és újra és újra ki kell értékeld.
És ha jön egy új böngésző, amiben megint másik felületen keresztül érhető el ugyanaz a funkció, akkor beleírsz egy újabb if-et? Ez pontosan hogyan viszonyul a csak egyszer kell megírni elvéhez?
Komolyan azt gondolod, hogy azok az emberek, akik rendelkeznek az általad vizionált nagy kereshető adatháló megvalósításához szükséges elméleti háttérrel, azok csak azért nem valósították eddig meg, mert még mindig azt tárgyalják, hogy mi legyen a színátmenetek szintakszisa?
Négy és félezer év alatt a könyvtárakban hányszorosára nőtt az írott szöveg óceánja? Mégsem született rá eljárás, hogy kereshető legyen. Lehet, hogy ez a probléma valamivel összetettebb, és valószínűleg ahhoz sincs köze, hogy a nyomdászok és rézmetszők a maguk dolgát végezték, és nem ezen dolgoztak.
Mi teszi
Mert a szoftvert mindenki arról ismeri, hogy elég egyszer megírni, és soha többet nincs vele dolog.
- hány százalékkal lett kevesebb munka a frontenden a HTML/CSS/JS szabványosítása miatt?
- hány százaléka a frontend egy teljes website elkészítési költségének?
- egy website-ra – teljes életciklusában – fordított összeg hány százaléka a frontend fejlesztés, és ezen belül mennyit nyertünk a szabványosítással?
Érzésem szerint nagyjából 1-2%-nyit. Tedd mellé a fenti tizenhatos számot, ami százalékban 1600, és rögtön igazolódik, hogy a szabványosítás a lehető legrosszabb döntés volt, amit a fejlesztők hozhattak. Hogy miért? Lásd lentebb.
Nekem semmi bajom a bigott
Religion is like a penis.
:)
Ez bölcs és szellemes
Amikor a téma arról szól,
Ha arról beszélünk, az OOP-ben hogyan oldható meg egy konkrét probléma, vagy miért fontosak a SOLID elvek, majd minden alkalommal megjelenik valaki, aki litániákat ír arról, hogy az OOP egyébként korlátozottan használható ezért és ezért, akkor egy idő után joggal merül fel a gyanú, hogy az illető fejében valami el van tájolva.
Furcsállom, hogy a különbség elsőre nem egyértelmű.
Rossz kérdés
ha már
handjob
blowjob
footjob
vaginal
anal
tegyük fel, hogy ezekről beszélünk, van akit érdekel az anal, vagy teljesen újfajta területet fedezne fel, erre jössz és azt mondod, hogy ne baszakodj már vele, mert handjob-bal tökéletesen ki lehet elégülni, és annál (anál :D) jobb nincs.
totál off már úgyis a szál.
A szál már az első
Nekem az jut eszembe, hogy amikor még PHP-ztam, a különféle PHP-s fórumokon is mindig volt valami fanatikus, aki kötelességének érezte minden témában megjegyezni, hogy ne használj PHP-t és akkor nem lesz ilyen gondod. Ezt hívom hittérítő típusnak.
Ha az a téma, sajtreszelővel
Ha valaki kérdést tesz fel, mert teszem azt kezdő, lehet neki tippeket adni, hogy sajtreszelő helyett használhatna inkább mást. Ez nyilván teljesen más eset.
A két bekezdésed között
Az általad gyakran
Fejlődés
Mint fentebb levezettem, teljesen indifferens az esetek túlnyomó többségében, hogy aszinkron kéréseket indítsanak, mert pont ugyanaz lesz a végeredmény, mintha szinkron lett volna. Ebben az esetben viszont miért szenvedjünk az aszinkron programozás hátrányaival?
Tavaly beküldtem egy blogmarkot, ahol leírják, hogy
This means that we lose the opportunity to learn and improve the current situation.
Most, hogy már Poetro is belépett mellettem a harcba, és megkérdőjelezte a PHP-ban az OOP használatának értelmét, úgy érzem, elindult egy pozitív változás.
PHP
PHP
Nem hiszem
Ha itt 2015-ben az aszinkron
Sajnos teljesen igazad van. Bár részemről nagyon örülök a blogmarkjaidnak, általuk (és néhány más blogmark által) a Weblabor legalább marginálisan érint modern webbel kapcsolatos témákat is. De most már be kell ismerjem magamnak, mindig hibát követek el, amikor érdeklődéssel telve elolvasom a hozzászólásokat egy ilyen előremutató, fontos blogmark alatt. Egyszerűen időpazarlás. Már megint és megint ugyanaz a lemez, egyetlen embernél beakadva, és mindenki neki próbálja elmagyarázni az alapokat. Erről szól a hozzászólások 100 %-a.
Áthelyezve kicsit a nézőpontot, tegyük fel, van egy receptoldal. Szeretnék valami jó receptet, amiben van tojás. Elolvasnám a hozzászólásokat is, mert feltételezem, hogy az adott receptről szólnak, mindenki leírja a tapasztalatait, biztosan megtudok olyat, aminek hála még sikeresebben használhatom a receptet, esetleg vitákat olvashatok a hozzáadott majoranna mennyiségét illetően (főleg mivel a régebbi receptek alatt mindig tanultam valami újat). Azonban mindez hiú ábránd, mivel valami megszállott minden receptet teleszpemmel azzal, hogy a tojás nem egészséges. Persze csakis a közös jó érdekében, hogy mindenki végre észbekapjon.
Nem kell túl komolyan venni ezt a hozzászólást persze. Itt az a furcsa "ügyfél" vagyok, aki nem hagyja ott az egészet a francba, hanem valami érthetetlen oknál fogva marad és időnként leírja, mi nem tetszik neki, nem mintha bármi változna tőle. Tessék ignorálni, az lesz a legjobb.
Nem vagyok belsős, így lehet nem tudok róla, hogy ez a Hidvégi valami VIP, vagy nemzetközi szaktekintély, vagy valakinek a valakije (mivel többször lett kérve, hogy vegyen vissza, de ezt leszarhatja minden következmény nélkül), de én unom a feltűnési viszketegségét és azt, hogy bármekkora zseninek képzeli magát, képtelen használni egy egyszerű fórumot. Ti. nyiss egy témát, ne pedig minden más témát offolj szét a hülyeségeiddel.
Nem feltétlenül várok erre válaszokat, csak le kellett írnom.
(:
- meg nem értett zseni, mint pl Liszt Ferenc, aki bizonyos dolgokban iszonyatosan megelőzte korát és a kortársak nem értették meg
- hobbija vagy munkája az érveléstechnika, annak is az a része, hogy hogyan lehet egy vitát hatékonyan elterelni a lényegről. tulajdonképpen jól fizetett tanácsadó valamely politikai pártban, és itt edz.
- troll
Eleinte én is csak csendben
A másik két kategóriát meg gondolkodás nélkül moderálnám :).
off - flame
Te mennyit?
Mindig az "ez se tetszik, az se".
Szerinted ez mennyire jobb? Gábor legalább segít is a kezdőknek és érdekes dolgot is szokott írni.
Vagy csak te nem olvastad.
Blokk 2
Miért nem az történik, hogy az adatok megérkezésekor visszakerül a vezérlés a hívó függvényhez? A hibaüzenetet meg mondjuk el lehetne érni egy függvénnyel vagy egy rendszerkonstanssal:
if (fajl === null && get_last_error() === FILE_NOT_FOUND) {
console.log('hehe');
}
Ha ezt megcsinálnák, nem kéne változtatni a szabványon, és nem kéne foglalkozni a videóban felsorolt problémák egyikével sem.
Majd hasznásználnak
A generátorokhoz változtatni
Azaz változtatni kellene a
Minek vacakolni?
Ráadásul ez olyan szabványváltoztatás, ami a JS kódereket nem érinti, a V8-ban egy óra alatt elvégzik a változtatásokat, és megúsznak hat év útkeresést.
Megtörtént
Ezt visszafelé kompatibilis
foo
értéke nem változik meg (hiszen szinkron a kód), ha areadFile
nem nyúl hozzá. Ha a vezérlés visszakerül az event loopba, akkor afoo
változhat.Pont ezt oldották meg az
async-await
konstrukcióval (ami mellesleg a C#-ból lett egy-az-egyben átvéve):Ezt nem visszafele
Most úgy működik a node, hogy IO esetén elindul a "blokkoló" folyamat, az adott kontextust eldobja a rendszer, és a végén a kapott értékekkel meghív egy callback-et.
Úgy lett volna jó, ha a "blokkoló" folyamat előtt elmentik az adott kontextust (memóriaállapotot), elindítják az IO-t, a végén meghívják motoron belül a callback-et, ami visszaállítja a kontextust, és feltölti a változókat. Így lenne pszeudo-szinkron bármely IO függvény, megmaradna a belső eseményvezérlés, és így térne át ma már mindenki js-re.
Nem
Ha nem akartak volna visszafele kompatibilisak lenni, akkor másik nyelvet használtak volna, mondjuk Go vagy C#, vagy pedig írhattak volna egy teljesen új nyelvet. Egyesek meg is tették, és V8 és JavaScript helyett Lua-t használnak.
De léteznek még más, Node.js-hez hasonló próbálkozások, mint a Vert.x, ami JVM alapon viszont nyelvektől függetlenül hoz egy Node.js-hez hasonló architektúrát, jelenleg Java, JavaScript, Ruby, Python, Groovy, Clojure, Scala és Ceylon támogatással.
Ennek az egésznek semmi köze
A C esetében ilyen incidental complexity a memóriamenedzsment, újabb nyelvekben ezt felváltotta a hulladékgazdálkodás, és már nem kell vele foglalkoznunk. Node.js esetében visszatértünk a gyökerekhez, ráterheltek egy belső rendszerjellemzőt a programozói közösségre, aminek az a következménye, hogy még ebben a node.js megjelenésétől számítva öt évvel későbbi előadásban is a pyramid of doom a központi probléma.
Senkit nem érdekel, hogy a readfile() az belül szinkron vagy aszinkron. Tehát nyugodtan mondhatták volna, hogy a readfile() és társai pszeudo szinkron (belül aszinkron) függvények, mert megtehették volna.
Ehelyett mit csináltak? Valahol olvastam, hogy 28 féle megoldás van a callback hellre, más nyelveket hoztak létre (coffee és társaik), ráadásul már szabványt is módosítanak miatta. Emellett ott van az npm, egymilliom modullal, amiben n-féleképp oldották meg ezt a problémát, nehezítve a karbantartást, fejlesztést, megértést.
Többek között azért kell
Így kapunk egy újrahasznosítható mintát, amit igényeink szerint másolhatunk, használhatunk tetszőleges JS környezetben. Úgy hallottam valakitől ebben a szálban, hogy ez jó dolog.
És mire van inkább szükség,
Tehát még egyszer kérdem: miért terheljük rá a programozókra az eseményvezérlés komplexitását (és ebből következően a callback hellt vagy a szabványmódosítást), amikor csak elhanyagolható számban lehetne kihasználni? Úgy hallottam valakitől ebben a szálban, hogy célszerű olyan megközelítést választani, ami több használati esetet old meg.
Jól hallottad :)
Valamint ha ezt a döntést a környezetre bízzuk, ahogy javaslod, akkor oda a hordozhatóság. Hacsak nem vezetjük be a szabványba, hogy hogyan kell megvalósítania a környezetnek, de akkor végülis ugyanott vagyunk a szabványosítás terén, csak az egyik esetben kifejezőbb lesz a nyelv, a másikban pedig leszűkítettük magunkat egy esetre.
Persze az lenne a legjobb, ha mindenttudó lények fejlesztenék ki a programozási nyelveket, és akkor lehetne mindent az elejétől fogva jól csinálni. De ez nem opció, így marad a tapasztalatok alapján történő szabványkovácsolás.
Mikor mire. Ezért kell jelölni, hogy melyik hívás aszinkron, és melyik nem.
Kérdések özöne
Mik az aszinkron hívás következményei? Miért kéne megváltozniuk bizonyos változód értékeinek? Tehetnek-e a szoftverkörnyezet (V8) programozói arról, hogy ezek biztosan ne változzanak meg?
Mi köze az egésznek a hordozhatósághoz és a szabványhoz? Mi köze van a szabványnak ahhoz, hogy egy rendszerfüggvény (esetünkben file_read()) hívása aszinkron vagy pszeudo-szinkron módon történik? Hol van leírva a szabványban, hogy függvények nem működhetnek pszeudo-szinkron módon? Miért nem tekinthetünk a file_read()-re úgy, mintha egy ugyanolyan művelet történne, mint egy egyszerű összeadásnál? Miért kell ezt a belső komplexitást kiexportálni, amikor az esetek 99,99%-ában a programozónak nincs rá szüksége? Ha viszont ezt kiexportálták, miért nem tettek bele kézi memóriamenedzsmentet, hogy még kifejezőbb legyen a nyelv? Miért csak 2009 után jött be a blokkolástól való félelem, előtte miért nem volt ilyen?
Egy hosszabb műveletet, mint például a képméretezés, szerintem amúgy sem aszinkron oldanál meg, hisz az adott szál válaszát blokkolná (hehe).
Ha mégegyszer átolvasod az
A blokkolástól meg szerintem azért kezdtek el félni, mert
Ezt a választ nem fogadom el,
Miért kéne megváltozniuk
Szinkron végrehajtáskor garanciát kapsz rá, hogy más nem nyúl a változóidhoz, amíg nálad van a vezérlés.
a
az első összeadás után ((a+a)+a
) megváltozik (és pl 4 lesz az eredmény). Ez baj. Ha azel1.onclick
nem fér hozzáa
-hoz, akkor meg az a baj. Ezt nem tudod feloldani transzparens módon.Mondhatnák azt, hogy oké,
De én azt vetettem fel, hogy
Minden egyes értékadás után
Még mindig túl sok
Más. Az elkézelt implicit aszinkron rendszeredben mi lenne itt az elvárt kimenet?
read
valami implicit aszinkron függvény (azaz elengedi a vezérlést azon a ponton, majd ha végzett, visszakapja), illetve aread
futása közben lefut a második függvény. Aread
nem látja aza
változót. És mi történik akkor, ha aread
valami párhuzamosan működő (valahol a threadben írtál már rá példát) függvény (azaz valamivel visszatér), mivel tér vissza?Az első példádnak így van
var b = read('b.txt');
szinkron_fuggveny();
Az első sorra érkezik a vezérlés, a háttérben elindul az a.txt beolvasása. A második sorra érkezik a vezérlés, párhuzamosan elindul a b.txt beolvasása. A harmadik sorra érkezik a vezérlés, szinkron függvény a következő, ekkor megvárja a rendszer a két fájl beolvasását, és utána futtatja.
A
console.log(a, read('a.txt'), a);
ekvivalens a következővel:console.log(a, belso_valtozo, a);
Tegyük fel, hogy az a.txt beolvasása tíz másodperc, ha közben rákattintanak az el2-re, akkor az
a++
utasítás szinkron, azaz a rendszer csak akkor hajtja végre, amikor az a.txt-t beolvasta.Mint a 22-es hozzászólásban írtam, az egész pszeudo-szinkron dolognak szerveroldalon látom értelmét, így a fenti onclick-es kérdésed szerintem indifferens.
Ki tudja
read
függvényed után a következő azonnal végrehajtódik.És ki tudja megfejteni, és
Egy saját függvény vagy metódus akkor lesz pszeudo-szinkron, ha van benne pszeudo-szinkron függvényhívás.
A fenti kód nagyjából ekvivalens a következővel (Bence cikke alapján):
try {
var a = yield promisify(read)('a.txt');
var b = yield promisify(read)('b.txt');
var c = b.toString() + yield promisify(read)('c.txt');
cache(e) {
...
}
});
Házi feladat: hogyan nézne ki ez generátorokkal?
Miért érdekes számodra ez az
Hogy tudjam, mit csinál ez a kód:
Ha a read() szinkronként fut, akkor egyértelmű a kimenet:
Pszeudo-szinkron feldolgozás
Lényegében ezt írtam én is
Az első példádban rossz a
Miért?
Ja, nem, mivel szinkron kód.
Mi lesz a kimenet, ha
Akkor lesz a kimenet a
Tehát ha generátorokat
Igen, mert az init() futása
Miért egy kliensoldali
Ezt nem értem, mire volt
Teljesen máshogy működik a
Szerveroldalon, ezzel szemben, ha jön egy kérés, akkor elvégzem a műveletet, összeállítom a választ, majd kiküldöm a kliensnek. Tehát a kérés beérkeztétől a válasz kiküldéséig folyamatosan dolgozik a gép, és ebbe beleszámít az is, hogy vár például az adatbázisra, hisz addig nem mehet ki semmi, amíg nem kapott eredményt. Az időfaktornak csak akkor van szerepe, ha egy IO kérésre a megadott elfogadható timeout-on belül nem érkezik semmi.
A Bence által vázolt példában az időzítő egy olyan eszköz, aminek a fentiek miatt csak kliensoldalon van értelme és szerepe, szerveroldalon nincs. Ezért kértem tőle szerveroldali példát, ahol információt hordoz az, hogy egy függvény szinkron vagy pszeudo-szinkron módon fut.
Szerver oldal
Értem, amit írsz, csak azt
Szerver oldal
Ok, akkor légy szíves,
OK, nálam most verted ki a
Szerveroldalon, ezzel
Én arról az atomi kérésről beszélek, ami a kliensről bejön, és amire választ is kell küldenem. Ezen az atomi egységen belül hol van szerepe az időnek?
Te abból indulsz ki, hogy
Mondjuk egy netbank felületén lekéri valaki az egyenleget.
Csak és kizárólag az egyenleg összegét kéred le valami AJAX-os eszközzel.
Szerinted mi fog történni szerver oldalon? Megsúgom: nem egy SELECT fut, ami kikapja az adatbázisból a számla aktuális egyenlegét...
Soros
Tehát nem fordulhat elő az, hogy a kimenetbe rossz sorrendben kerül a bájtfolyam, erről a programozónak kell gondoskodnia. Ha pedig így van, akkor továbbra sem értem, milyen plusz információt hordoz az, hogy egy függvényt generátorokkal írok meg, ahhoz képest, mintha minden IO-t végző függvény automatikusan pszeudo-szinkron lenne.
Én itt léptem be a társalgásba
"Az a probléma, hogy te úgy tekintesz a szerver oldalra, mintha az csak egy HTTP szerver lenne, ami fájlokat szolgál ki. Pedig a kép ennél sokkal összetettebb."
Én itt léptem be.
Ennek mi köze ahhoz amit most rajtam próbálsz számon kérni?
(off: fura... számonkérés egy szó, de számon kérni kettő???)
Nem akarok beleszolni, de ez
az egész pszeudo-szinkron
Akkor hagy fogalmazzam át a problémát:
Kétféle IO művelet van: 1,
1, folyamatos, például egy fájl beolvasása vagy adatbázis-lekérdezés; ilyenkor lehet és van értelme használni pszeudo-szinkron függvényeket
2, időben változó, például websocket, amin véletlenszerűen jönnek az adatcsomagok, ilyenkor jobb híján marad a callback-es vagy ekvivalens megoldás
Ismét az a legfontosabb kérdés, hogy az esetek túlnyomó többségében miből van több, az előbbiből vagy az utóbbiból.
Ismét az a legfontosabb
Az én kódjaimban inkább utóbbiból, azaz folyamatosan van rengeteg stream, amiből adatot olvasok. Ezek fájlok, HTTP lekérések, és olvasások adatbázisból. Mindegyik stream-ként jelenik meg számomra, leginkább azért így folyamatosan fel tudom dolgozni a bejövő adatokat, nem kell várnom, hogy megjöjjön a vége (főleg mivel rengeteg memóriát megenne, ha megvárnám).
És te vagy "az esetek
Remélem
Egy körre én is beszállok :D
Tegyük fel, hogy van egy oldalam, ahol adott terméket lehet keresni, legyen könyv és keressünk a címe alapján.
Van 10 bolt, amelyeknek van nyilvános API-ja a keresésre.
Kérnék tőled egy olvasható pszeudo-szinkron kódot, amely azt valósítja meg, hogy ezek a kérések párhuzamosan futnak, de egyszerre maximum csak 5.
Nem érdekel, ha szerinted nem életszerű, kérném a kódot.
Ezt roppant egyszerűen
var valtozo2 = pszeudo('http://bolt2.hu/api?keres');
var valtozo3 = pszeudo('http://bolt3.hu/api?keres');
//random szinkron parancs, addig várunk, amíg mind meg nem érkezik az összes válasz
i++;
Nekem még nem kerek
-hogy kezdem el megjeleníteni egy válasz megérkezésének időpontjában az eredményt?
Az első kérdést nem értem. A
var valtozo2 = pszeudo_olvas('api2?keres');
pszeudo_kuld(valtozo1); //addig vár, amíg a valtozo1 felszabadul
pszeudo_kuld(valtozo2);
//random szinkron parancs, azután jut ide a futás, miután kiküldtük mindkét változó tartalmát
i++;
Az első kérdés
10db pszeudo_olvas kérést kell lefuttatnom összesen, de azt szeretném, hogy 5nél több ne fusson párhuzamosan egyszerre.
Tehát van egy 10 hosszú sorom, amiből egyszerre max 5-öt tudok feldolgozni.
Megjegyzés:
mennyire olvasható az a kód, ami formailag nem tesz különbséget pszeudo szinkron függvények, változók és szinkron társaik között. Vagy ha különbséget is tesz, mennyire olvasható a végeredmény, melyben az aszinkron és szinkron blokkok ugyanúgy néznek ki?
Az első kérdésre így a
Megjegyzésedhez: A kód ugyanúgy nézne ki flow szempontjából, mint egy php kód. Nem jut eszembe olyan eset, amikor pszeudo-szinkron függvények mellett valódi aszinkron hívásra lenne szükség callback-es megoldással.
első kérdés: tehát a http
tehát a http kérés végén egy callback-ben ellenőrzöm, hogy van-e a sorban még elem és ha van elkezdem futtatni? értem :D
megjegyzés. bocsánat, rosszul fogalmaztam. mennyire olvasható az a kód amelyben a pszeudo-szinkron (de aszinkron futó) folyamatok és a ténylegesen szinkron futó részek ugyanúgy néznek ki?
Kérdésedre: Pl. meghívod a
wait_until_all_asynchronous_calls_finished()
függvényt.Megjegyzésedhez: Miért fontos számodra tudni, azaz mit kezdesz azzal az információval, hogy a rendszer a háttérben szinkron vagy pszeudo-szinkron módon tölti fel a változód egy függvényhívásnál?
kérdés minek hívjam meg a
minek hívjam meg a függvényt, ha a következő szinkron hívás alapból meghívja?
szóval hogyan garantálom, hogy 5-nél több ne fusson, mert ezt még mindig nem tudom.
megjegyzés
performancika (persze a mai világban minden olyan gyors, hogy nem számít). szóval írok egy kódot, megtervezem, hogy ezek a részek fussanak szépen párhuzamosan ha van rá mód, aztán jön pistike beszúr egy szinkron kérést, a példánál maradva mondjuk a http kérést indító és a választ feldolgozó függvények közé, és hopp, nem úgy működik ahogy kellene és fogalmunk sincs miért.
Kérdésedre: Azért kell
Megjegyzésedre: kommentelj vagy gondolkodj egy kicsit, mit lehet kihozni az adott körülményekből. Aszinkron hívások mellett is lehet hülyeségeket csinálni, hogy megakaszd az egész szerver futását.
Végül pedig a pszeudo-szinkron függvények léte nem zárja ki, hogy mellettük ott legyenek a hagyományos, aszinkron változataik. Probléma megoldva.
kérdés: de ha 5
de ha 5 pszeudo-szinkron kérés után rakok egy wait_until... akkor lesz, hogy 4,3,2,1 fut csak egyszerre, de én azt szeretném hogy mindig fusson 5, amíg van feldolgozatlan kérés. lásd Poetro hozzászólását.
callback-es esetben nem igazán értem, hogy hogyan lehet a következő sorban megakasztani a dolgokat véletlenül. elindult a folyamat, le fog futni.
azt értem, hogy a pszeudo szinkron függvények léte nem zárja ki az aszinkron függvények létezését, csak azt nem értem, hogy akkor az aszinkron hívások elfedésére miért hoztuk létre a pszeudo szinkron függvényeket, hiszen azok "teljesen egyenértékűek". ja bocs mégsem. értem.
Nem érted
1, minden aszinkron, és jön vele a callback hell, és eltelik bő fél évtized, mire megoldást találnak a problémára (mert a programozók már csak olyan esendők, hogy a soros végrehajtást tudják hatékonyan leprogramozni),
vagy
2, minden pszeudo-szinkron, ami mellett lehetőséget adunk a renitenseknek arra, hogy futassák aszinkron, amit az úri kedvük szeretne.
Már unalmas ez a jössz mindig
Szerintem nagyon sokan örülnének itt ha utána néznél dolgoknak mielőtt repetitíven mindig ugyanazt mondogatod...de a callback hell de a callback hell.
Köszönöm
1, mekkora az io.js elterjedtsége a teljes node.js spektrumban?
2, az npmjs.com-on lévő jelenleg kb. 120 000 csomagból hányban használják ki ezt a lehetőséget?
Node 0.11
Például
co
nevű generátor alapú aszinkron könyvtárra közel 300 modul támaszkodik.Nem arrol van szo hogy a
A librarykben ugy is es5 kompatibilis kodnak kell lennie hogy mindenki tudja hasznalni...viszont a Promiseok ott is elerhetoek mar library formajaban.
De, ez nagyon fontos
1, Értenem kell a kódját, hogy ha hiba van, tudjam, mi okozta. Ha tele van callback-ekkel, vagy pyramid of doom, akkor nem fogom megérteni.
2, Ugyanígy problémát okozhat a karbantartás is, mert egy nagyobb modul kódját nem feltétlenül fognak átírni a szerzői az újabb elvek szerint, és előbb-utóbb megy a kukába.
Ahol mar a forraskodjat kell
Ez nem valtoztat azon h a sajat kododnal tudod hasznalni mar ma
EM.synchrony
Anno 1.9-es ruby verzióval megjelentek Fiber-ek a nyelvben (ezek pehelysúlyú konkurenciát támogató elemek) és az akkor már relatíve elterjedt EventMachine nevű reactor-pattern libhez elkészült az EM-Synchrony kiterjesztés.
Ez a már emlegetett "callback-hell"-re ad megoldást, olvasmány: Untangling Evented Code with Ruby Fibers.
Az eredmény kódban valahogy így néz ki (példák fenti linkről):
További kutatásra ajánlom az eventmachineról szóló előadásokat itt: confreaks.
A dolog fő hátulütője persze az, hogy fiber/eventmachine-re felkészített driverekre van szükséged mindenre amit ezekben a szinkronizációs blokkokban akarsz csinálni párhuzamosan, mint DB (legyen az sql vagy nosql) lekérdezések, HTTP requestek és így tovább. Ruby közösség egy sor ilyet írt népszerűbb dolgokhoz, és nekem úgy tűnik ez a fajta "aranyláz" nemsoká megindul majd JS világban is csak "generator-aware" lesz a buzzword "fiber-aware" helyett.
Fibers elérhető node-hoz is,
Jelenlegi módszerre
100!