• ú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í
      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...
      REFLEX
      REFLEX --- ---
      3108: diky moc, super odkazy

      Ja to napsal blbe, co kdyz potrebuju i ten this z runneru i ten z MyObject? :D Protoze jestli chapu spravne tak diky arrow mi zustane jen ten MyObject this
      3108
      3108 --- ---
      Postupov je niekolko, zalezi aku verziu node pouzivas, ja doporucujem pouzit latest, a mas tam arrow function spolu s lexical scoping... https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

      Ak node pouzit nemozes, tvoj sposob zauzivany, ja prefreujem v tychto pripadoch, pouzitie explicitneho .bind https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
      REFLEX
      REFLEX --- ---
      Zdravim,

      jsem Node.js zacatecnik :D

      Mam objekt a v nem volam jiny objekt s callbackem, jak se uvnitr dostanu do this MyObject a ne this toho runner

      Ted to resim pres ten var self = this;

      
      
      function MyObject() {
          this.runner = new Runner();
      }
      
      MyObject.prototype.run = function() {
          var self = this;
      		
          this.runner.run(function(res) {
              // ZDE!
              // this je v kontextu runner
              // pouzivam self je MyObject definovany vyse
           });
      };
      
      NEPH04
      NEPH04 --- ---
      Sorry za <OT>, ale kdyby jste někdo chtěl, nebo věděl o někom, kdo umí:

      Potřebujeme člověka do týmu SOCIFI, který povede vlastní dlouhodobý projekt (Node nebo PHP) od návrhu až po konečnou realizaci a další rozvoj.
      Projekt je unikátní a cílený na klienty z celého světa. Bude to nová část naší platformy.
      Měl by mít zkušenost s návrhem API, znalost databází MySQL/MongoDB, základní znalost administrace Linux serverů.
      Hodně nadprůměrné platové ohodnocení a benefity. Nástup ihned. :)
      URPUTNIK
      URPUTNIK --- ---
      CYNIK: chm, to jsi uz druhej kdo varuje pred problemy s ssh u githubu .. ja s tim kazdopadne zadnej problem nemel :) nakonec jsme to stejne prehodili na https + public repo v githubu, kolegove na widlich s tim ssh dost bojujou :))
      CYNIK
      CYNIK --- ---
      URPUTNIK: taky bejvá problém s ssh adresou na githubu, jistější je HTTPS
      URPUTNIK
      URPUTNIK --- ---
      URPUTNIK: tak jsem to mel spravne, zakopanej pes byl ve verzi, musi splnovat semanticke verzovani .. takze stacilo zmenit 3.2 na 3.2.0 .. 6h casu, achjo
      URPUTNIK
      URPUTNIK --- ---
      URPUTNIK: chm, tady je asi odpoved, zkusim zitra
      URPUTNIK
      URPUTNIK --- ---
      zdravim, zkousim se dopatrat toho, jestli (a jak) lze vystavit vlastni npm modul ve vlastnim git repozitari a pak ho linkovat odnekud jinud..
      myslel jsem ze stacit mit v tom gitu package.json se jmenem a verzi, ktera odpovida git tagu .. a ten kdo linkuje, pak pouziva
        'fooModule':"git+ssh://git@kdekoli:123/foo.git#verze"
      

      ale "npm install" mi to nedava:
      npm ERR! addLocal Could not install /tmp/npm-7084-3c28cb63/git-cache-35639714/1bab0c48b57045d0dd61ca895d42943a7c5c6132
      npm ERR! Linux 3.16.0-4-amd64
      npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install"
      npm ERR! node v6.4.0
      npm ERR! npm  v3.10.6
      
      npm ERR! Invalid version: "3.2"
      

      presto se to z toho repozitare stahlo v poradku, viz:
      
      $ head /tmp/npm-7084-3c28cb63/git-cache-35639714/1bab0c48b57045d0dd61ca895d42943a7c5c6132/package.json 
      {
        "name": "foo",
        "version": "3.2",
        "private": true,  
        "devDependencies": {},
        "dependencies": {},
        "scripts": {} 
      }
      
      Kliknutím sem můžete změnit nastavení reklam