• úvod
  • témata
  • události
  • tržiště
  • diskuze
  • nástěnka
  • přihlásit
    registrace
    ztracené heslo?
    ANGEL333node.js - Evented I/O for V8 JavaScript

    Věříte, že nějaký webapp framwork postavený na node.js (Express?) bude v budoucnosti rozšířený podobně jako jsou nyní např. Django, CakePHP, Rails, Zend, atd..?

    55 hlasy od 55 respondentů

      Relativně nové server-side javascriptové API. Hlavní předností je, že je event-driven a neblokující. Již nyní obsahuje implementaci protokolů HTTP, TCP, DNS, rozhraní pro práci s procesy, soubory, atd..

      Instalace je velmi jednoduchá, jediná závislost je Python, potom node.js nainstalujete jako standardní program.

      Odkazy:


    • Oficiální web: http://nodejs.org

    • Přednáška od Ryana Dahla (autor node.js)

    • Git repozitář: http://github.com/ry/node
    • rozbalit záhlaví
      FEDY
      FEDY --- ---
      FIKOTEK: nebo nejdrive navazat spojeni z pocitace treba websocketem a do socketu to pak posilat
      CUCHULAIN
      CUCHULAIN --- ---
      FIKOTEK: nasadit nějaký dynamický DNS na ten cílový počítač?
      FIKOTEK
      FIKOTEK --- ---
      Potrbuju odeslat http request na pocitac ktery neni ve stejne siti jako pocitac ze ktereho ten request posilam. Ten pocitac na ktery bych rad poslal ten request je za routrem ktery mu prideluje pres DHCP nejakou IP adresu. Tusite jak tohle vyresit?
      GIOMIKY
      GIOMIKY --- ---
      DARKIE: Díky za tip s SVG.
      DARKIE
      DARKIE --- ---
      GIOMIKY: kvoli comu potrebujes obrazok?
      pokial kvoli tomu aby si mel predkresleny graf uz z nejakych hodnot, a potom donho on the fly dokresloval, tak mas principialne dve moznosti.
      1. na serveri si nakreslit obrazok ako tu uz kalicor povedal tam to moc s canvasom nepojde, asi pouzit nieco ine. nacitat si obrazok a vkreslit ho do canvasu a potom canvas prekreslovat.
      2. imho lepsia vec na toto, pouzit SVG, SVG je super v tom ze je to viacmenej DOM, takze ho vies "kreslit" aj na serveri tym ze si vyrobis ten string, na clientovi vies do SVG cez DOM metody pristupovat a menit ho. Toto samozrejme vsak iba vtedy ak mas v HTML embednute cele SVG a nemas ho tam referencovane cez img src=nieco.svg
      KALICOR
      KALICOR --- ---
      GIOMIKY: zkousim pochopit otazku:
      - chces generovat ten graf na klientovi? (posles JSON ajax/websocket, canvas jeto) anebo ciste server side?
      - na to prvni mi nesedi ten gif - dovedu si predstavit ze vygeneruji graf na canvas udelam PNG data a ty soupnu do img src, popr. poslu na server ...
      - to druhe - jelikoz bych se s tim asi nechtel moc crmcat - bych asi pouzil a PhantomJS nebo tak neco - pouzivali jsme to na generovani custom nahledu map ke vsi spokojenosti, ALE z hlediska service apod. by byla spravnejsi cesta mit k NodeJS knihovnu ktera bude generovat GIF/PNG/anything, tu se ale rozluc s CANVAS - server side neni browser - zadny getContext2D/3D pokud vim. i kdyz ve svete Javascrptu si clovek neni nikdy jistej co soudruzi vymysleli :D
      GIOMIKY
      GIOMIKY --- ---
      Dotaz (doufam, ze do spravneho klubu) ... mam html canvas ... a generuji na nej nejake grafy (viz. obrazek)... a chtel bych, aby se mi v prohlizeci zobrazil pouze obrazek... ale aby to bylo tak, ze uz se do prohlizece nacte primo obrazek... uz jsem zkousel takovy ty legrace s tim, ze si prepisu nahrany html gifem, ktery se objevi, kdyz vygeneruji blob. .. ale neni to ono... lze to nejak (mozna mi unika podstata) ... a to ta, ze javascript se provadi na klientovi a ja bych to chtel asi generovat na serveru.. je to tak? Da se nejak generovat gif z canvasu primo v node.js?

      DARKIE
      DARKIE --- ---
      REFLEX: ja len ze je imho trochu semanticky nespravne aby this vnutri objektu runner ukazovalo na nieco ine ako runner

      ak chces vramci runnera bezat nieco z myobjectu tak by som to zapisal takto

      this.runner.run(this.another_function.bind(this));

      samozrejme si potrebujes naprototypovat v myobject another_function a nie pouzivat anonymous funkciu.

      takto sa nestratis ked budes v buducnosti ten kod ty alebo niekto iny citat
      UETOYO
      UETOYO --- ---
      GitHub - facebook/prepack: Prepack is a partial evaluator for JavaScript. Prepack rewrites a JavaScript bundle, resulting in JavaScript code that executes more efficiently.
      https://github.com/facebook/prepack
      FEDY
      FEDY --- ---
      AREX: to je to co jsem prave napsal - jen 1x "worker_mysql: sending to main process" a nekolikrat "mod_subnets: received from SQL worker". bude to moje chyba asi ve zpracovani tech eventu ale nevim jaka
      AREX
      AREX --- ---
      FEDY: Tohle uz asi uplne nesouvisi s NodeJS :) S workery nemam zkusenosti, takze neporadim snad jen krome toho dat si logovani i tam kde to posilas jestli to opravdu je jenom jednou.
      FEDY
      FEDY --- ---
      AREX: tak jsem dosel k tomu, ze to dela ta mapa (visjs) - stale jsem nevypnul fyziku a dokud se body neustali, tak to pocita jako vztekle. jakmile zazoomuju tak aby byly videt 2-3 body (asi to nejni tolik vytizene), violations zmizi ...

      ale, mam jeste jeden dotaz - v nodejs si vytvarim child procesy forkem. napr. pro mysql operace, aby mi to nezdrzovalo hlavni proces. doposud vse ok - select, insert, update, retez nekolika udalosti select a potom insert / update - vse ok. ale nyni jsem narazil - child process mi v logu pise, ze odesila data do hlavniho procesu (jednou) a hlavni proces zarve, ze data obdrzel nekolikrat - tedy jakoby se on event volal vicekrat (?) nedelam nejakou zasadni blbost ? nebo to delam cele spatne ?

      worker_mysql: Found 1 subnet in MYSQL.
      worker_mysql: sending to main process {"err":false,"sqlAction":"select","sqlTable":"subnet","rows":[{"id_subnet":1,"prefixSize":24,"network":"10.133.36.0","purpose":0,"id_node":-1}]}
      ^^^
      child process hlasi 1x odeslani

      ....ale hlavni proces nekolikrat prijeti....

      mod_subnets: received from SQL worker {"err":false,"sqlAction":"select","sqlTable":"subnet","rows":[{"id_subnet":1,"prefixSize":24,"network":"10.133.36.0","purpose":0,"id_node":-1}]}
      mod_subnets: subnet 10.133.36.0 exists in database
      mod_subnets: received from SQL worker {"err":false,"sqlAction":"select","sqlTable":"subnet","rows":[{"id_subnet":1,"prefixSize":24,"network":"10.133.36.0","purpose":0,"id_node":-1}]}
      mod_subnets: subnet 10.133.36.0 exists in database
      mod_subnets: received from SQL worker {"err":false,"sqlAction":"select","sqlTable":"subnet","rows":[{"id_subnet":1,"prefixSize":24,"network":"10.133.36.0","purpose":0,"id_node":-1}]}
      mod_subnets: subnet 10.133.36.0 exists in database
      mod_subnets: received from SQL worker {"err":false,"sqlAction":"select","sqlTable":"subnet","rows":[{"id_subnet":1,"prefixSize":24,"network":"10.133.36.0","purpose":0,"id_node":-1}]}
      mod_subnets: subnet 10.133.36.0 exists in database


      hlavni proces vola child takto
                      global.sql.worker.send(request);
                      global.sql.worker.once('message', function(resp) {
                          console.log(_Fname+': received from SQL worker '+JSON.stringify(resp));
                          if (resp.err == false && resp.sqlTable == 'subnet' && resp.sqlAction == 'select') {
                              if (resp.rows.length === 0) {
                                  console.log(_Fname+': subnet does not exist in database');
                                  var insertRequest = [{sqlAction: 'insert', sqlTable: 'subnet', network: subnet.networkAddress, prefixSize: subnet.subnetMaskLength,  purpose: purpose, id_node: router }];
                                  global.sql.worker.send(insertRequest);
                                  return
                              } else {
                                  console.log(_Fname+': subnet '+resp.rows[0].network+' exists in database');
                                  return
                              }
                          }
                      });
                      global.sql.worker.once('message', function(resp) {
                          if (resp.err == false && resp.sqlTable == 'subnet' && resp.sqlAction == 'insert') {
                              console.log(_Fname+': subnet inserted with ID '+resp.insertId);
                              return
                          }
                      });
      

      --------------------------------------------------

      a child odpovida takto
      process.on('message', function(data) {
          console.log('worker_mysql: rececived data '+JSON.stringify(data));
          var table = data[0].sqlTable;
          var action = data[0].sqlAction;
          delete data[0].sqlTable;
          delete data[0].sqlAction;
      
          switch(action) {
      
              case "select":
      
                  select(table,data,function(err,table,rows) {
                      if (err) {
                          var result = { err: true, sqlAction: action, sqlTable: table, rows: null };
                      } else {
                          var result = { err: false, sqlAction: action, sqlTable: table, rows: rows };
                      }
                      console.log('worker_mysql: sending to main process '+JSON.stringify(result)+'');
                      process.send(result);
                      return
                  });
              break;
      
              case "insert":
      
                  insert(table,data,function(err,insertId,dataOut) {
                      if (err) {
                          var result = { err: true, sqlAction: action, sqlTable: table, insertId: null, object: null };
                      } else {
                          var result = { err: false, sqlAction: action, sqlTable: table, insertId: insertId, object: dataOut };
                      }
                      console.log('worker_mysql: sending to main process '+JSON.stringify(result)+'');
                      process.send(result);
                      return
                  });
      
              break;
      
              case "update":
      
              break;
              default:
      
              break;
      
          } 
      


      nevim proc, ale NYX nejak zkomolil ten zdrojak :-) snad tomu je rozumnet...
      AREX
      AREX --- ---
      FEDY: Nevim cim kreslis to co tam kresleny, ale skoro bych hledal zdroj problemu tam. Vsadim, ze cele to vykresleni je synchronni zalezitost a jestli to delas primo v reakci na prijata data, tak je o to horsi.

      Obecne neni dobre na udalosti (tedy i prijata data) reagovat okamzite. Naopak by sis mel jen ty data ulozit do nejake promenne. A pak pouzij `requestAnimationFrame`, ktery by cist naposledy prijata data a vykresli to podle nich. Ta funkce ti rika, kdy je nejoptimalenejsi neco vykreslovat.
      AREX
      AREX --- ---
      FEDY: "Handler took 504ms of runtime" ... to samo o sobe ti rika, ze dlouho trvalo zpracovani dat, ktere jsi prijal pres Socket.io. Pojem handler znamena obvykle funkce/callback, ktera reaguje na nejakou udalost.

      Jinak doporuju si v browseru dat socket.io do blackboxu, pak ti to melo ukazovat trochu uzitecnejsi informace. https://developer.chrome.com/devtools/docs/blackboxing
      FEDY
      FEDY --- ---
      AREX: cili myslis, ze to blokuje neco, co je volano pri prichozich datech ? me to uplne neprijde, obzvlast kdyz jsem si prohledl profiler - same funkce ze socket.io

      AREX
      AREX --- ---
      FEDY: Nerekl bych, ze ta chyba souvisi se SocketIO. Tohle znamena, ze ta bezi nejaky synchronni skript, ktery je bud extremne pomaly a nebo nikdy neskonci. Castym zdrojem jsem neukoncene rekurzivni smycky. SocketIO komunikace je asynchronni a nemuze tedy browser blokovat ani kdyby chtelo :)
      FEDY
      FEDY --- ---
      ahoj,

      jsem v javascriptu a nodejs zacatecnik, tedy prosim o shovivavost - pisu dohledovy system pro nasi sit (ping, snmp, syslog atp) a narazil jsem na knihovne SocketIO v prohlizeci - jakmile mam prilis objektu, zacnou se objevovat violations "script took too long time" atp. mate nekdo predstavu, jak to resit ? nahradit SocketIO treba za EngineIO ? nebo jeste neco jineho ?

      predem diky
      AREX
      AREX --- ---
      PANVA: Chápu. Ačkoliv vím, že třeba Babel transpiluje async funkce do generatorů. V případě NodeJS to je irelevantní vzhledem k nadcházející nativní podpoře.

      Asi to budu muset taky vyzkoušet. Jsem totiž kdysi kdesi narazil na článek detailně rozebírající porovnání těchto dvou a hodně to tam generátory vyhrávaly z různých důvodů. Co me teda těší už takhle od pohledu, že async funkce mohou být i anonymní. To u generátoru nejde a to pak produkuje antipatterny jako `const self = this`. Ačkoliv vzhledem k tomu, že Koa2 už není závislá na contextu, tak na tom tolik nesejde.
      PANVA
      PANVA --- ---
      AREX: pouzit generatory za pomoci `co` ktery neustale vola .next() na ten generator byl jen work around, intention od zacatku byl async/await ktery je jen pekny wrapper okolo promisu.

      Generator - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*
      Async Fn - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

      Dovedu si predstavit ze async funkce ma mnohem mensi rezii nez generator a zatimco prepisuju celou moji openid connect libku (https://github.com/panva/node-oidc-provider) na koa2 zjistuji jak jednodussi mam praci napr. s testovanim jednotlivych middlewaru
      CUCHULAIN
      CUCHULAIN --- ---
      AREX: netuším vůbec, o co jde, ale dost často je právě ta volnost problém. umožňuje vytvořit těžko hledatelné chyby.
      AREX
      AREX --- ---
      Používáte někdo KoaJS? Víte někdo co je vedlo k tomu zahodit použití generatoru a přejít na async/await? Dělal jsem už s obojím a přijde mi, že generátory dávají daleko větší volnost.
      3108
      3108 --- ---
      REFLEX: chapem presne co myslis, potrebujes v tom cb handleri mat referenciu na MyObject (idealne ako this) a potom refernciu na runner, ale tu by som za tychto okolnosti predaval explicitne ako dalsi agument handleru, za `res`.

      Kazdopadne je tento pristup z mojho pohladu code-smell, explicitne predavanie referencii casto znamena "leaking abstraction" a zaroven sa tym narusa SRP + miesto CB by som pouzil Promise...
      Kliknutím sem můžete změnit nastavení reklam