2013. július 17., szerda

Az az egyik gondom JS-el, hogy minden aszinkron.

Az az egyik gondom JS-el, hogy minden aszinkron. Ez amúgy praktikus, mert nem blokkol, viszont a kód elveszti a linearitását, és olvashatatlanabb lesz. Tehát mondjuk olyat akarok, hogy letöltök egy adatbázist, megnyitom, és futtatok egy lekérdezést. Azt nem tehetem meg így lineárisan, hanem a letöltés hív egy callback-et, amiben a db megnyitás hív egy callback-et, amiben a lekérdezés hív egy callback-et, ahol végre megjelenik az eredmény. De az egész vagy egymásba ágyazott névtelen függvények halmaza, vagy definiálhat az ember minden callback-nek külön fv.-t, a helyett, hogy ilyet írna:

dbfile = load(url);
db = db_open(dbfile);
result = db.query(...);

Erre jó lenne valami, akár valami cross-compileres megoldás is, hogy lineárisan lehessen írni a kódot, amit aztán átalakít ilyen callback-es formába.

Balazs Nadasdi (vélemény? mint JavaScript témában legkompetensebb ismerős :))

14 megjegyzés:

  1. Hazaértem írok, de most még kerekezek

    VálaszTörlés
  2. A Dart-os async Future mára már elég jó, ott lehet olyant mondani hogy valami()
      .then((x) {})
      .then((y) {})
      .then((z) {})
      .then((z2) {});

    Azaz az egymásba ágyazható callback-ek helyett van egy szép lineáris kódod. Valaki azt mondta régebben, hogy ez a node.js-es projekt nagyon hasonlót csinál, de én nem néztem meg közelebbről:
    https://github.com/coolaj86/futures

    VálaszTörlés
  3. Van promise és a legtöbb linn tud vele mit kezdeni. De mér mindjárt otthon :-) csak pirosat kaptam.

    VálaszTörlés
  4. Istvan Soos Azért ez sem a legszebb megoldás, mert itt meg a then-ek szabdalják szét a kódot. Illetve azt nem értem még, hogy mit ad vissza a then, amire a másik then-t hívod, és hol mondod meg neki, hogy akkor hívódjon meg, mikor letöltöttél valamit, aztán a következő akkor, mikor megnyitod a db-t, stb.

    VálaszTörlés
  5. Nah itthon.

    Eloszor is van az ugynevezett Promise. Ez azt mondja, hogy "Megigerem, hogy itt lesz valami". Aztan van success meg fail fuggvenye igy pl lancolhato is akar.

    Sok (pl fs.*) lib-nek van Sync fuggvenye is. Ezen kivul a sajat cuccaidhoz csinalhatsz valami keretet amivel mondjuk megoldod, hogy User.findById(userId) es ez egy igerettel ter vissza.

    Van sok ORM ami mar ezt biztositja szamodra, ha adatbazisrol van szo:
     - http://bookshelfjs.org/
     - http://knexjs.org/

    Nekem viszont sok esetben fuggetlen keresekhez kell, amit meg az adatbazik libbel es az async segitsegevel meg is oldok. Pelda:
    Oldal betoltesekor:
    [kategorialista lekerdezese, cimkek lekerdezese, felhasznalo lekerdezese, adott tartalmanak lekerdezese], ha ez vegzett (async parallel kerdezes utani success fuggveny) rendereljuk le az oldalt.

    Ezen kivul pedig en sose csinalok fo agban olyat (nah jo ritkan ha csak valami demohoz kell az anyag), hogy egymasba pakolok 4-5 callback-et. Altalaban ha ilyen a mertek akkor olyanokrol van szo amik amugy is osszetartoznak es csinalok inkabb egy kulon file-t, amiben van egy fuggveny mondjuk getUser(), ami visszater a userrel es a hozza tartozo dolgokkal. Abban lehet tobb egymasba agyazas, mert kommentelem es nagy esellyel ritkan nyulok hozza. A fo agamban meg csak 1 callback lesz. Lehet parametereztetni is, hogy pl amennyiben nem kell bizonyos adat, akkor a fuggveny ne hivjon kerjen tobbet, hanem terjen vissza azzal ami adott szinten van.

    Teny neha kenyelmetlen, de sok esetben nem (legtobb esetben). Ez olyan, hogy mas nyelvekben is sok esetben kenyelmetlen minden losz@rnak egy class-t csinalni, vagy epp mindenhol lekerdezni adott dolgot, mert nem fer hozza es nem oldhato meg erdelmesen es ezert meg 3 class kell, hogy tudjon ferni.

    VálaszTörlés
  6. Amugy meg pl tok logikus :)

    Elinditod az appot. Kapcsolodsz adatbazishoz, kiertelmezed a tobbi konfiguraciot, betoltod a szukseges dolgokat. Parhuzamosan. Ha mindegyik vegzett, akkor inditod a figyelest portra :)

    VálaszTörlés
  7. Laszlo Fazekas A Dart-os Future.then() visszatérhet egy új Future-el, és akkor automatikusan láncolódnak. Itt egypár példa arra, hogy hogyan is néz ki, ha pl. masszívan aszinkron műveleteid vannak egymás után a tesztekben:
    https://github.com/agilord/riak_dart_client/blob/master/test/local_http_test.dart

    VálaszTörlés
  8. Istvan Soos mondjuk azt nem ertem miert volt jo atnevezniuk a tok talalo nevu Promise-t Future-ra :)

    VálaszTörlés
  9. Balazs Nadasdi De ezek mind ilyen áthidaló megoldások, és mindenhol kell legalább 1 callback. Én valami olyasmit tartanék szépnek, ahol minden eseménykezelő olyan mint ha külön thread-et indítana, amiben viszont lineárisan írhatod a dolgokat olyan fv,-ekkel, amik blokkolnak. Tehát ilyen, amit írtam:

    dbfile = load(url);
    db = db_open(dbfile);
    result = db.query(...);

    Ehhez mondjuk mindenképp valami előfordító kellene, ami ezt csinálja belőle:

    load(url, function(dbfile) {
      db_open(dbfile, function(db) {
        db.query(..., function(result) { ... })
      })
    })

    Ezt mondjuk fordító nélkül nem biztos, hogy meg lehet csinálni, de szerintem jópofa lenne egy ilyen js-js fordító, ami mondjuk figyeli, hogy @fvnév-el hívsz egy fv.-t, akkor így alakítja át.

    VálaszTörlés
  10. Istvan Soos Na, akkor már a future-t értem. De a legelegánsabb szerintem az lenne, amit írtam. :)

    VálaszTörlés
  11. Laszlo Fazekas szerintem felesleges :) Es meg mindig jobb mint a java, ahol 400 class-t csinalsz csak mert ugy fog mukodni es kevesebbol mar nem fer hozza mindenhez ^^. =P

    VálaszTörlés
  12. Laszlo Fazekas Volt erről több vizsgálódás, arról is hogy mit lehet hatékonyan megcsinálni előfordítóval ill. mi az ami hatékonyan futtatható a VM-en. A legutolsó vélemény szerint a Dart-ban nem lesz előfordító, hanem úgynevezett async block-ok, ahol kb. lineáris felsorolással megcsinálhatod azt, amit pl. a Future láncolással. Az előfordítónak több hasfájása is van, pl. ha az egyik hívás nem csak egyetlen async műveletet generál, akkor nehéz megmondani helyesen, hogy hol van a scope-határ.

    VálaszTörlés
  13. Istvan Soos Lehet, de ilyen egyszerű esetekre praktikus lenne. Több callback-re persze nem használható. Ezekről az async block-okról van valahol doksi?

    Balazs Nadasdi Azért Java-val sem kell mindent agyament módon csinálni. Attól, hogy néhányan agyamenten használják, még nem a nyelv szar. :)

    VálaszTörlés
  14. Én csak egy előadásra emlékszem kb. az idei Google IO előttről egy kicsivel, doksit nem láttam. Mivel még csak kísérleti buildekben van belőle futó példány, ezért még nem vennék belőle semmit sem biztosra :)

    VálaszTörlés