Acasă - Antivirusuri
Variabilele globale ale nodului js. Bazele Nodejs

Într-un nod, puteți seta variabile globale printr-un obiect „global” sau „GLOBAL”:

GLOBAL._ = require("subliniere"); // dar „nu ar trebui” să faci asta! (vezi nota de mai jos)

sau mai util...

GLOBAL.window = GLOBAL; // ca în browser

Din sursa nodului puteți vedea că sunt aliasuri unul pentru celălalt:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = global;

În codul de mai sus, „acest” este contextul global. Cu modulul commonJS (pe care îl folosește nodul), acest „obiect” din interiorul modulului (adică „codul tău”) NU este contextul global. Pentru dovada acestui lucru, vedeți mai jos unde am aruncat „acest” obiect și apoi uriașul obiect „GLOBAL”.

Console.log("\nACEST:"); console.log(aceasta); console.log("\nGLOBAL:"); console.log(global); /* iese... ACEST: {} GLOBAL: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT: 2 ), ( Int32BYTES_PER_ELEMENT:_32 BYTES_PER_ELEMENT:_3) PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , proces: ( EventEmitter: , titlu: "nod", assert: , versiune: "v0.6.5", _tickCallback: , moduleLoadList: [ „Evaluări de legare”, „Evaluări de legare”, „Evenimente NativeModule”, „Buffer NativeModule”, „Buffer de legare”, „Afirmare NativeModule”, „Util NativeModule”, „Calea NativeModule”, „Modulul NativeModule”, „ NativeModule fs”, „Legarea fs”, „Constante de legare”, „Fluxul NativeModule”, „Consola NativeModule”, „Legarea tty_wrap”, „NativeModule tty”, „NativeModule net”, „Tronometre NativeModule”, „Legarea timer_wrap”, „ NativeModule _linklist" ], versiuni: ( nod: "0.6.5", v8: "3.6.6.11", ares: "1.7.5-DEV", uv: "0.6", openssl: "0.9.8n"), nextTick : , stdout: , arch: „x64”, stderr: , platformă: „darwin”, argv: [ „nod”, „/workspace/zd/zgap/darwin-js/index.js” ], stdin: , env: ( TERM_PROGRAM: "iTerm.app", "COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET": "/tmp/launch-nNl1vo/ServiceProcessSocket:m",/:" TERMSHELLSocket:m",/:"/" , TMPDIR: „/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/”, Apple_PubSub_Socket_Render: „/tmp/launch-9Ga0PT/Render”, UTILIZATOR: „ddopson”, COMMAND_MODE: „SOCKSH:_00Hmp”, „SOCK:_00Htp”, „SOCK:_00Hmp”, lansați -sD905b/Listeners", __CF_USER_TEXT_ENCODING: "0x12D732E7:0:0", PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/ X11 /bin”, PWD: „/workspace/zd/zgap/darwin-js”, LANG: „en_US.UTF-8”, ITERM_PROFILE: „Implicit”, SHLVL: „1”, COLORFGBG: „7;0”, HOME : „/Utilizatori/ddopson”, ITERM_SESSION_ID: „w0t0p0”, LOGNAME: „ddopson”, DISPLAY: „/tmp/launch-l9RQXI/org.x:0”, OLDPWD: „/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , ieșire: , pid: 10321, caracteristici: ( depanare: fals, uv: adevărat, ipv6: adevărat, tls_npn: fals, tls_sni: adevărat, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , debug: , eroare: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , moștenește: , _kill: , _byteLength: , mainModule: ( id: ". ", exportă: (), părinte: null, nume fișier: "/workspace/zd/zgap/darwin-js/index.js", încărcat: fals, ieșit: fals, copii: , căi: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInterval: , clearInterval: , clearInterval consola: , fereastra: , navigator: () ) */

**Notă: În ceea ce privește setarea „GLOBAL._”, în general, ar trebui să faceți doar var _ = require ("subliniere"); Da, faci asta în fiecare fișier care folosește caracterul de subliniere, la fel ca în Java importi com.foo.bar; Acest lucru face mai ușor să determinați ce face codul dvs., deoarece legăturile dintre fișiere sunt „explicite”. Ușor enervant, dar bun. Aceasta este o predică.

Există o excepție de la fiecare regulă. Am avut exact un caz în care trebuia să setez „GLOBAL._”. Cream un sistem pentru definirea fișierelor „config” care erau în mare parte JSON, dar „scrise în JS” pentru a adăuga puțin mai multă flexibilitate. Nu existau instrucțiuni „require” în astfel de fișiere de configurare, dar am vrut ca acestea să aibă acces la subliniere (întregul sistem se baza pe modele de subliniere și subliniere), așa că aș seta „GLOBAL._” înainte de a evalua „config”. Deci da, pentru fiecare regulă există o excepție undeva. Dar ai un motiv întemeiat, nu doar „M-am săturat să tastez”, așa că vreau să încalc acordul”.

Un student a întrebat: „Programatorii de altădată foloseau doar computere simple și programau fără limbaje, dar făceau programe frumoase. De ce folosim calculatoare complexe și limbaje de programare?” Fu-Tzu a răspuns: „Clădirii de altădată foloseau doar bețe și lut, dar au făcut colibe frumoase.”

Maestrul Yuan-Ma, „Cartea programării”

Până acum, ați învățat JavaScript și l-ați folosit într-un singur mediu: browserul. În acest capitol și în următorul, vom prezenta pe scurt Node.js, un program care vă permite să utilizați abilitățile JavaScript în afara browserului. Cu el puteți scrie totul, de la utilitare de linie de comandă la servere HTTP dinamice.

Aceste capitole se concentrează pe predarea ideilor importante care alcătuiesc Node.js și sunt concepute pentru a vă oferi suficiente informații pentru a vă permite să scrieți programe utile în cadru. Ele nu încearcă să fie referințe cuprinzătoare pentru Node.

Puteți scrie și executa codul din capitolele anterioare direct în browser, dar codul din acest capitol a fost scris pentru Node și nu va funcționa în browser.

Dacă doriți să rulați imediat codul din acest capitol, începeți prin a instala Node de pe nodejs.org pentru sistemul dvs. de operare. Tot pe acest site veți găsi documentație despre Node și modulele sale încorporate.

Introducere

Una dintre cele mai dificile probleme atunci când scrieți sisteme care comunică printr-o rețea este gestionarea intrărilor și ieșirii. Citirea și scrierea datelor către și de la rețea, disc și alte dispozitive. Mutarea datelor necesită timp, iar planificarea adecvată a acestei activități poate avea un impact semnificativ asupra timpului de răspuns al sistemului pentru solicitările utilizatorilor sau ale rețelei.

În procesarea tradițională de intrare și ieșire, o funcție precum readFile începe să citească fișierul și revine numai atunci când fișierul a fost citit complet. Aceasta se numește I/O sincron (intrare/ieșire).

Node a fost proiectat pentru a face I/O asincronă mai ușor și mai ușor de utilizat. Am văzut deja interfețe asincrone, cum ar fi obiectul browser XMLHttpRequest, discutat în Capitolul 17. O astfel de interfață permite scriptului să continue să ruleze în timp ce interfața își face treaba și apelează o funcție de apel invers când este terminat. Acesta este modul în care funcționează toate I/O în Node.

JavaScript se potrivește cu ușurință într-un sistem precum Node. Aceasta este una dintre puținele limbi care nu are un sistem I/O încorporat. Deci JavaScript se încadrează cu ușurință în abordarea destul de excentrică a I/O a lui Node și nu ajunge să dea naștere la două sisteme de intrare și ieșire diferite. În 2009, când dezvoltau Node, oamenii utilizau deja I/O bazate pe callback în browser, așa că comunitatea din jurul limbajului era obișnuită cu un stil de programare asincron.

Asincronie

Voi încerca să ilustrez diferența dintre abordările sincrone și asincrone ale I/O cu un mic exemplu, în care un program trebuie să primească două resurse de pe Internet și apoi să facă ceva cu datele.

Într-un mediu sincron, modalitatea evidentă de a rezolva problema este de a face interogări secvenţial. Această metodă are un minus - a doua cerere va începe numai după ce prima s-a terminat. Timpul total nu va fi mai mic decât suma timpului de procesare a două cereri. Aceasta este o utilizare ineficientă a computerului, care va fi inactiv de cele mai multe ori în timp ce datele sunt transferate prin rețea.

Soluția problemei într-un sistem sincron este lansarea unor fire suplimentare de control al execuției programului (le-am discutat deja în Capitolul 14). Un al doilea thread poate rula o a doua cerere, iar apoi ambele fire vor aștepta ca rezultatul să fie returnat, după care vor fi resincronizate pentru a converge munca într-un singur rezultat.

În diagramă, liniile groase indică timpul normal de funcționare a programului, iar liniile subțiri indică timpul de așteptare I/O. În modelul sincron, timpul petrecut pe I/O este inclus în programul de timp al fiecărui thread. În asincron, declanșarea unei acțiuni prin I/O duce la o ramificare a liniei de timp. Firul de execuție care a lansat I/O continuă execuția, iar I/O-ul este executat în paralel, făcând o funcție de apel invers la finalizare.

Flux de program pentru I/O sincron și asincron

O altă modalitate de a exprima această diferență: în modelul sincron, așteptarea sfârșitului I/O este implicită, dar în modelul asincron, este explicită și este sub controlul nostru direct. Dar asincronia funcționează în ambele sensuri. Ea facilitează exprimarea programelor neliniare, dar face mai dificilă exprimarea programelor în linie dreaptă.

În capitolul 17, am atins deja faptul că apelurile inverse introduc mult zgomot și fac un program mai puțin organizat. Dacă această abordare este în general o idee bună, este discutabil. În orice caz, este nevoie de timp să te obișnuiești.

Dar pentru un sistem bazat pe JavaScript, aș spune că utilizarea asincronă cu apeluri inverse are sens. Unul dintre punctele forte ale JavaScript este simplitatea, iar încercarea de a adăuga mai multe fire într-un program ar duce la multă complexitate. Deși apelurile inverse nu simplifică codul, ideea din spatele lor este foarte simplă și totuși suficient de puternică pentru a vă permite să scrieți servere web de înaltă performanță.

comanda nodului

Când Node.js este instalat pe sistemul dvs., aveți un program numit node care rulează fișiere JavaScript. Să presupunem că aveți un fișier hello.js cu următorul cod:

Var mesaj = „Bună lume”; console.log(mesaj);

Puteți rula programul din linia de comandă:

$node hello.js Bună lume

Metoda console.log din Node funcționează în același mod ca și în browser. Afișează o bucată de text. Dar în Node, textul este tipărit la ieșirea standard, mai degrabă decât în ​​consola JavaScript din browser.

Dacă rulați node fără un fișier, acesta vă va oferi un șir de interogare în care puteți scrie cod JavaScript și obține rezultatul.

$ nod > 1 + 1 2 > [-1, -2, -3].map(Math.abs) > ​​​​process.exit(0) $

Variabila de proces, ca și consola, este disponibilă global în Node. Acesta oferă mai multe moduri de a inspecta și de a manipula un program. Metoda de ieșire încheie procesul și i se poate transmite un cod de stare de ieșire a programului, care spune programului care a lansat nodul (în acest caz, shell-ul) dacă programul a ieșit cu succes (cod zero) sau a eșuat (orice alt număr).

Pentru a accesa argumentele liniei de comandă transmise programului, puteți citi matricea de șiruri process.argv. Include, de asemenea, numele comenzii nod și numele scriptului dvs., astfel încât lista de argumente începe la indexul 2. Dacă fișierul showargv.js conține doar o instrucțiune console.log(process.argv), o puteți rula astfel :

$ node showargv.js unu --și doi [„nod”, „/home/marijn/showargv.js”, „unu”, „--și”, „două”]

Toate variabilele globale JavaScript standard - Array, Math, JSON, sunt de asemenea disponibile în mediul Node. Dar nu există nicio funcționalitate legată de browser, cum ar fi documentul sau alerta.

Obiectul de acoperire globală, numit fereastră în browser, este mai semnificativ numit global în Node.

Module

În afară de câteva variabile menționate, cum ar fi consola și procesul, Node păstrează puține funcționalități în domeniul global. Pentru a accesa restul capabilităților încorporate, trebuie să accesați sistemul de module.

Sistemul CommonJS, bazat pe funcția require, a fost descris în Capitolul 10. Acest sistem este încorporat în Node și este folosit pentru a încărca totul, de la biblioteci încorporate și descărcate la fișiere care fac parte din programul dumneavoastră.

Când apelați require Node, trebuie să convertiți șirul dat într-un nume de fișier. Căile care încep cu „/”, „./” sau „../” sunt convertite în căi relativ la cea curentă. „./” înseamnă directorul curent, „../” înseamnă directorul de mai sus și „/” înseamnă directorul rădăcină al sistemului de fișiere. Dacă solicitați „./world/world” din fișierul /home/marijn/elife/run.js, Node va încerca să încarce fișierul /home/marijn/elife/world/world.js. Extensia .js poate fi omisă.

Când trece un șir care nu pare a fi o cale relativă sau absolută, se presupune că este fie un modul încorporat, fie un modul instalat în directorul node_modules. De exemplu, require("fs") vă va oferi un modul încorporat pentru a lucra cu sistemul de fișiere și require("elife") va încerca să încarce biblioteca de la node_modules/elife/. Metoda tipică pentru instalarea bibliotecilor este utilizarea NPM, la care voi reveni mai târziu.

Pentru a demonstra, să facem un proiect simplu cu două fișiere. Primul se va numi main.js și va defini un script numit din linia de comandă, conceput pentru a distorsiona șirurile.

Var garble = cere("./garble"); // Indexul 2 conține primul argument de program din linia de comandă var argument = process.argv; console.log(garble(argument));

Fișierul garble.js definește o bibliotecă de deformare a șirurilor care poate fi utilizată atât de programul de linie de comandă pe care l-ați definit mai devreme, cât și de alte scripturi care necesită acces direct la funcția garble.

Module.exports = function(string) ( return string.split("").map(function(ch) ( return String.fromCharCode(ch.charCodeAt(0) + 5); )).join(""); ) ;

Înlocuirea module.exports în loc să îi adăugăm proprietăți ne permite să exportăm o anumită valoare dintr-un modul. În acest caz, rezultatul solicitării modulului nostru va fi funcția de distorsiune în sine.

Funcția împarte un șir în caractere folosind split cu un șir gol și apoi înlocuiește toate caracterele cu altele cu un cod cu 5 unități mai mare. Apoi concatenează rezultatul înapoi într-un șir.

Acum putem apela instrumentul nostru:

$ node main.js JavaScript Of(fXhwnuy

Instalare prin NPM

NPM, menționat pe scurt în Capitolul 10, este un depozit online de module JavaScript, dintre care multe sunt scrise special pentru Node. Când instalați Node pe computer, obțineți un program npm care oferă o interfață convenabilă pentru acest depozit.

De exemplu, unul dintre modulele NPM se numește figlet și transformă textul în „art ASCII”, desene formate din caractere text. Iată cum se instalează:

$ npm instalează figlet npm GET https://registry.npmjs.org/figlet npm 200 https://registry.npmjs.org/figlet npm GET https://registry.npmjs.org/figlet/-/figlet-1.0. 9.tgz npm 200 https://registry.npmjs.org/figlet/-/figlet-1.0.9.tgz [email protected] module_noduri/figlet $ nod > var figlet = require("figlet"); > figlet.text("Bună lume!", function(eroare, date) ( if (eroare) console.error(eroare); else console.log(date); )); _ _ _ _ _ _ _ | | | | ___| | | ___ __ _____ _ __| | __| | | | |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| „__| |/ _` | | | _ | __/ | | (_) | \ V V / (_) | | | | (_| |_| |_| |_|\___|_|_|\ ___/ \_/\_/ \___/|_|

După rularea npm install, NPM va crea un director node_modules. În interiorul acestuia va exista un director figlet care conține biblioteca. Când pornim nodul și apelăm require(„figlet”), biblioteca este încărcată și îi putem apela metoda text pentru a tipări litere mari, fanteziste.

Ceea ce este interesant este că, în loc să returneze pur și simplu un șir care conține majuscule, figlet.text acceptă o funcție de apel invers căreia îi transmite rezultatul. De asemenea, trece acolo un alt argument, error, care va conține un obiect de eroare în cazul unei erori și nul în caz de succes.

Acest principiu de funcționare este adoptat în Node. Pentru a crea litere, figlet trebuie să citească un fișier de pe disc care conține litere. Citirea unui fișier este o operație asincronă în Node, așa că figlet.text nu poate returna rezultatul imediat. Asincronia este contagioasă - orice funcție care apelează una asincronă devine ea însăși asincronă.

NPM este mai mult decât instalarea npm. Citește fișierele package.json, care conțin informații JSON despre program sau bibliotecă, în special pe ce biblioteci se bazează. Rularea npm install în directorul care conține un astfel de fișier va instala automat toate dependențele și, la rândul lor, dependențele acestora. Instrumentul npm este, de asemenea, folosit pentru a găzdui biblioteci în depozitul online NPM, astfel încât alte persoane să le poată găsi, descărca și utiliza.

Nu vom mai intra în detalii despre utilizarea NPM. Consultați npmjs.org pentru documentația despre căutarea în biblioteci.

modul de sistem de fișiere

Unul dintre cele mai populare module Node încorporate este modulul „fs”, care înseamnă „sistem de fișiere”. Modulul oferă funcționalitate pentru lucrul cu fișiere și directoare.

De exemplu, există o funcție readFile care citește un fișier și face un apel invers cu conținutul fișierului.

Var fs = require("fs"); fs.readFile(„fișier.txt”, „utf8”, function(eroare, text) (dacă (eroare) aruncare eroare; console.log(„Și fișierul conține:”, text); ));

Al doilea argument pentru readFile specifică codificarea caracterelor în care să convertiți conținutul fișierului într-un șir. Textul poate fi convertit în date binare în multe moduri, dar cel mai nou este UTF-8. Dacă nu aveți niciun motiv să credeți că fișierul conține text într-o codificare diferită, puteți trece în siguranță parametrul „utf8”. Dacă nu specificați o codificare, Node vă va oferi datele codificate binar ca obiect Buffer, mai degrabă decât un șir. Acesta este un obiect asemănător matricei care conține octeți dintr-un fișier.

Var fs = require("fs"); fs.readFile("fișier.txt", function(eroare, buffer) ( dacă (eroare) aruncare eroare; console.log ("Fișierul conținea ", buffer.length, " octeți.", "Primul octet:", buffer ); ));

O funcție similară, writeFile, este utilizată pentru a scrie un fișier pe disc.

Var fs = require("fs"); fs.writeFile(„graffiti.txt”, „Nodul a fost aici”, function(err) ( if (err) console.log(„Nimic nu a funcționat și iată de ce:”, err); else console.log(„Scrie cu succes . Toată lumea este liberă."); ));

Nu este nevoie să setați codificarea aici, deoarece writeFile presupune că, dacă i se dă un șir de scris, și nu un obiect Buffer, atunci ar trebui să fie scos ca text cu codificarea implicită UTF-8.

Modulul „fs” conține o mulțime de lucruri utile: funcția readdir returnează o listă de fișiere dintr-un director ca o matrice de șiruri de caractere, stat va returna informații despre un fișier, redenumește un fișier, deconecta ștergerile etc. Consultați documentația la nodejs.org

Multe funcții fs au atât opțiuni sincrone, cât și asincrone. De exemplu, există o versiune sincronă a funcției readFile numită readFileSync.

Var fs = require("fs"); console.log(fs.readFileSync(„fișier.txt”, „utf8”));

Funcțiile sincrone sunt mai ușor de utilizat și mai utile pentru scripturile simple în care viteza adăugată a unei metode asincrone nu este importantă. Dar rețineți că, în timp ce acțiunea sincronă rulează, programul dvs. se oprește complet. Dacă trebuie să răspundă la intrarea utilizatorului sau la alte programe din rețea, așteptarea I/O sincronă cauzează întârzieri enervante.

Modul HTTP

Un alt modul principal este „http”. Oferă funcționalitate pentru crearea de servere HTTP și solicitări HTTP.

Iată tot ce aveți nevoie pentru a porni un server HTTP simplu:

Var http = require("http"); var server = http.createServer(funcție(cerere, răspuns) ( response.writeHead(200, ("Content-Type": "text/html")); response.write("

Buna ziua!

Ai solicitat " + request.url + "

"); response.end(); )); server.listen(8000);

Prin rularea scriptului pe mașina dvs., puteți îndrepta browserul către localhost:8000/hello, creând astfel o solicitare către server. Va răspunde cu o pagină HTML mică.

Funcția transmisă ca argument pentru createServer este apelată de fiecare dată când se încearcă o conexiune la server. Variabilele de cerere și răspuns sunt obiecte care reprezintă date de intrare și de ieșire. Prima conține informații despre cerere, de exemplu proprietatea URL conține adresa URL a cererii.

Pentru a trimite ceva înapoi, se folosesc metodele obiectului răspuns. Primul, writeHead, scrie anteturile răspunsurilor (vezi capitolul 17). Îi dați un cod de stare (în acest caz 200 pentru „OK”) și un obiect care conține valorile antetului. Aici îi spunem clientului că ar trebui să aștepte un document HTML.

Apoi vine corpul răspunsului (documentul în sine), trimis prin response.write. Această metodă poate fi apelată de mai multe ori dacă doriți să trimiteți răspunsul în bucăți, de exemplu, transmiterea datelor în flux pe măsură ce sosesc. În cele din urmă, response.end semnalează sfârșitul răspunsului.

Apelarea server.listen face ca serverul să asculte cererile pe portul 8000. Prin urmare, trebuie să mergeți la localhost:8000 în browser, și nu doar localhost (unde portul implicit va fi 80).

Pentru a opri un script Node care nu se termină automat deoarece așteaptă evenimente ulterioare (în acest caz, conexiuni), trebuie să apăsați Ctrl-C.

Un server web real face mult mai mult decât ceea ce este descris în exemplu. Se uită la metoda de solicitare (proprietatea metodei) pentru a înțelege ce acțiune încearcă să efectueze clientul și la adresa URL a solicitării pentru a înțelege pe ce resursă ar trebui efectuată acțiunea respectivă. În continuare, veți vedea o versiune mai avansată a serverului.

Pentru a face un client HTTP, putem folosi funcția modulului de solicitare „http”.

Var http = require("http"); var cerere = http.request(( nume gazdă: "eloquentjavascript.net", cale: "/20_node.html", metoda: "GET", antete: (Accept: "text/html") ), funcția (răspuns) (consolă .log("Serviciul a răspuns cu codul ", response.statusCode )); cerere.end();

Primul argument de cerere configurează cererea, spunându-i lui Node cu ce server vom comunica, ce cale va lua cererea, ce metodă să folosească etc. A doua este funcția. care va trebui apelat la finalul cererii. I se transmite un obiect de răspuns, care conține toate informațiile despre răspuns - de exemplu, codul de stare.

La fel ca obiectul de răspuns al serverului, obiectul returnat prin cerere vă permite să transmiteți date cu metoda write și să încheiați cererea cu metoda end. Exemplul nu folosește scrierea deoarece cererile GET nu ar trebui să conțină date în corp.

Pentru solicitările de securizare a URL-urilor (HTTPS), Node oferă modulul https, care are propria funcție de solicitare similară cu http.request.

Fluxuri

Am văzut două exemple de fluxuri în exemplele HTTP - obiectul răspuns, pe care serverul poate scrie și obiectul cerere, care este returnat de la http.request.

Fluxurile care pot fi scrise sunt un concept popular în interfețele Node. Toate firele au o metodă de scriere, căruia i se poate transmite un șir sau un obiect Buffer. Metoda end închide fluxul și, dacă există un argument, va imprima o bucată de date înainte de închidere. Ambelor metode li se poate da o funcție de apel invers printr-un argument suplimentar, pe care îl vor apela când înregistrarea este finalizată sau fluxul este închis.

Este posibil să creați un flux care să indice un fișier folosind funcția fs.createWriteStream. Apoi, puteți utiliza metoda de scriere pentru a scrie în fișier în bucăți, mai degrabă decât ca un întreg, ca în fs.writeFile.

Fluxurile care pot fi citite vor fi puțin mai complicate. Atât variabila de cerere transmisă funcției de apel invers din serverul HTTP, cât și variabila de răspuns transmisă în clientul HTTP sunt fluxuri care pot fi citite. (Serverul citește cererea și apoi scrie răspunsuri, iar clientul scrie cererea și citește răspunsul). Citirea dintr-un flux se face prin handlere de evenimente, nu prin metode.

Obiectele care creează evenimente în Node au o metodă on, similară cu metoda addEventListener a browserului. Îi dai un nume de eveniment și o funcție și înregistrează acea funcție, astfel încât să fie apelată imediat când are loc evenimentul.

Fluxurile care pot fi citite au evenimente „date” și „sfârșit”. Primul apare la sosirea datelor, al doilea la finalizare. Acest model este potrivit pentru streaming de date care pot fi procesate imediat, chiar dacă nu este primit întregul document. Fișierul poate fi citit ca flux prin fs.createReadStream.

Următorul cod creează un server care citește corpurile cererii și le trimite înapoi ca un flux de text cu majuscule.

Var http = require("http"); http.createServer(function(request, response) ( response.writeHead(200, ("Content-Type": "text/plain")); request.on("date", function(chunk) ( response.write(chunk) .toString().toUpperCase()); request.on("end", function() ( response.end(); )).listen(8000);

Variabila chunk transmisă handler-ului de date va fi un buffer binar, care poate fi convertit într-un șir prin apelarea metodei sale toString, care o decodifică din codificarea implicită (UTF-8).

Următorul cod, atunci când rulează simultan cu serverul, va trimite o solicitare către server și va imprima răspunsul primit:

Var http = require("http"); var cerere = http.request(( nume gazdă: „localhost”, port: 8000, metodă: „POST”), funcție (răspuns) ( răspuns.on(„date”, funcția (porțiune) (proces.stdout.write(bucătură) .toString()); request.end("Salut server");

Exemplul scrie în process.stdout (ieșirea standard a procesului, care este un flux care poate fi scris) mai degrabă decât în ​​console.log. Nu putem folosi console.log pentru că adaugă o întrerupere de linie suplimentară după fiecare fragment de cod - nu este necesar aici.

Server de fișiere simplu

Să combinăm noile noastre cunoștințe despre serverele HTTP și lucrul cu sistemul de fișiere și să construim o punte între ele: un server HTTP care oferă acces de la distanță la fișiere. Există multe cazuri de utilizare pentru un astfel de server. Permite aplicațiilor web să stocheze și să partajeze date sau poate oferi unui grup de persoane acces la un set de fișiere.

Când tratăm fișierele ca resurse HTTP, metodele GET, PUT și DELETE pot fi folosite pentru a citi, scrie și șterge fișiere. Vom interpreta calea din cerere ca fiind calea către fișier.

Nu trebuie să expunem întregul sistem de fișiere, așa că vom interpreta aceste căi ca fiind relative la directorul rădăcină, iar acesta va fi directorul de lansare al scriptului. Dacă pornesc serverul de la /home/marijn/public/ (sau C:\Users\marijn\public\ pe Windows), atunci o solicitare către /file.txt ar trebui să indice /home/marijn/public/file.txt ( sau C :\Utilizatori\marijn\public\file.txt).

Vom construi programul treptat, folosind obiectul methods pentru a stoca funcții care se ocupă de diferite metode HTTP.

Var http = require("http"), fs = require ("fs"); var metode = Object.create(null); http.createServer(funcție(cerere, răspuns) (funcția răspunde(cod, corp, tip) (dacă (!tip) tip = „text/plain”; response.writeHead(cod, („Conținut-Tip”: tip)) ; if (body && body.pipe) body.pipe(response else response.end(body) if (request.method în metode) (urlToPath(request.url), respond, else respond(); "Metoda " + request.method + " nu este permisă )).listen(8000);

Acest cod va porni serverul returnând erori 405 - acest cod este folosit pentru a indica faptul că metoda solicitată nu este acceptată de server.

Funcția de răspuns este transmisă funcțiilor care se ocupă de diferite metode și acționează ca un callback pentru a finaliza cererea. Acceptă un cod de stare HTTP, un corp și, eventual, un tip de conținut. Dacă corpul transmis este un flux care poate fi citit, va avea o metodă pipe care este utilizată pentru a transmite un flux care poate fi citit la un flux care poate fi scris. Dacă nu, se presupune că este fie nul (corpul este gol), fie un șir de caractere și apoi este transmis direct la metoda răspunsului final.

Pentru a obține calea de la o adresă URL într-o solicitare, funcția urlToPath folosește modulul „url” încorporat din Node pentru a analiza adresa URL. Este nevoie de un nume de cale, ceva de genul /file.txt, decodifică pentru a elimina %20 de coduri de evadare și inserează un punct de început pentru a obține calea relativă la directorul curent.

Crezi că funcția urlToPath este nesigură? Ai dreptate. Vom reveni asupra acestei probleme în exerciții.

Vom proiecta metoda GET pentru a returna o listă de fișiere când citim un director și conținutul unui fișier când citim un fișier.

Întrebarea adevărată este ce tip de antet Content-Type ar trebui să returnăm când citim un fișier. Deoarece ar putea fi ceva într-un fișier, serverul nu poate returna același tip pentru toată lumea. Dar NPM poate ajuta cu asta. Modulul mime (indicatorii tipului de conținut al fișierului, cum ar fi text/plain, sunt denumiți și tipuri MIME) cunoaște tipul corect pentru un număr mare de extensii de fișiere.

Rulând următoarea comandă npm în directorul în care se află scriptul serverului, puteți utiliza require("mime") pentru a interoga biblioteca de tipuri.

$ npm install mime npm http GET https://registry.npmjs.org/mime npm http 304 https://registry.npmjs.org/mime [email protected] module_nod/mime

Când fișierul solicitat nu există, codul de eroare corect pentru acest caz este 404. Vom folosi fs.stat pentru a returna informații despre fișier pentru a afla dacă un astfel de fișier există și dacă este un director.

Metode.GET = function(cale, respond) ( fs.stat(path, function(error, stats)) ( if (eroare && error.code == "ENOENT") respond(404, "File not found"); altfel dacă (eroare) respond(500, error.toString()); else if (stats.isDirectory()) fs.readdir(cale, function(error, files) (if (eroare) respond(500, error.toString()) ; else respond(200, files.join("\n")); else respond(200, fs.createReadStream(path), require("mime").lookup(path));

Deoarece interogările pe disc necesită timp, fs.stat rulează asincron. Când fișierul nu există, fs.stat va transmite un obiect de eroare cu proprietatea de cod „ENOENT” către funcția de apel invers. Ar fi grozav dacă Node ar defini diferite tipuri de erori pentru diferite erori, dar nu este așa. În schimb, scuipă coduri confuze în stil Unix.

Vom emite toate erorile neașteptate cu codul 500, indicând că există o problemă pe server - spre deosebire de codurile care încep cu 4, care indică o problemă cu cererea. În unele situații, acest lucru nu va fi în întregime precis, dar pentru un program eșantion mic va fi suficient.

Obiectul stats returnat de fs.stat ne spune totul despre fișier. De exemplu, dimensiunea este dimensiunea fișierului, mtime este data modificării. Aici trebuie să aflăm dacă acesta este un director sau un fișier obișnuit - metoda isDirectory ne va spune acest lucru.

Pentru a citi o listă de fișiere dintr-un director, folosim fs.readdir, iar printr-un alt apel invers, o returnăm utilizatorului. Pentru fișierele obișnuite, creăm un flux care poate fi citit prin fs.createReadStream și îl transmitem în răspuns, împreună cu tipul de conținut pe care modulul mime l-a produs pentru acel fișier.

Codul de manipulare DELETE va fi mai simplu:

Metode.DELETE = function(cale, respond) ( fs.stat(path, function(error, stats) ( if (error && error.code == "ENOENT") respond(204); else if (error) respond(500) , error.toString()); else if (stats.isDirectory()) fs.rmdir(path, respondErrorOrNothing(respond)); else fs.unlink(path, respondErrorOrNothing(respond));

S-ar putea să vă întrebați de ce încercarea de a șterge un fișier care nu există returnează o stare 204 în loc de o eroare. Putem spune că atunci când încercați să ștergeți un fișier inexistent, deoarece fișierul nu mai este acolo, cererea a fost deja executată. Standardul HTTP încurajează oamenii să facă cereri idempotente, adică solicitări în care repetarea aceleiași acțiuni de mai multe ori nu produce rezultate diferite.

Funcția respondErrorOrNothing(răspunde) ( return function(error) (dacă (eroare) respond(500, error.toString()); else respond(204); ); )

Când răspunsul HTTP nu conține date, puteți utiliza codul de stare 204 („fără conținut”). Deoarece trebuie să oferim funcții de apel invers care fie raportează erori, fie returnează un răspuns 204 în diferite situații, am scris o funcție specială respondErrorOrNothing care creează un astfel de apel invers.

Iată handlerul cererii PUT:

Methods.PUT = function(cale, respond, request) ( var outStream = fs.createWriteStream(path); outStream.on("eroare", function(error) ( respond(500, error.toString()); )); outStream.on("finish", function() ( respond(204); )); request.pipe(outStream);

Aici nu trebuie să verificăm existența fișierului - dacă acesta există, îl vom suprascrie pur și simplu. Din nou, folosim pipe pentru a transfera date dintr-un flux de citire într-un flux de scriere, în cazul nostru de la o solicitare la un fișier. Dacă firul de execuție nu poate fi creat, se generează un eveniment „eroare”, pe care îl raportăm în răspuns. Când datele sunt transferate cu succes, pipe va închide ambele fluxuri, determinând declanșarea evenimentului „finish”. Și după aceea putem raporta succesul cu codul 204.

Scriptul complet al serverului este aici: eloquentjavascript.net/code/file_server.js. Poate fi descărcat și rulat prin Node. Desigur, poate fi schimbat și completat pentru a rezolva exerciții sau experimente.

Utilitarul curl de linie de comandă, disponibil public pe sistemele Unix, poate fi folosit pentru a crea cereri HTTP. Următorul fragment testează serverul nostru. –X este folosit pentru a specifica metoda cererii, iar –d este folosit pentru a include corpul cererii.

$ curl http://localhost:8000/file.txt Fișierul nu a fost găsit $ curl -X PUT -d salut http://localhost:8000/file.txt $ curl http://localhost:8000/file.txt salut $ curl -X DELETE http://localhost:8000/file.txt $ curl http://localhost:8000/file.txt Fișierul nu a fost găsit

Prima solicitare către file.txt eșuează deoarece fișierul nu există încă. Solicitarea PUT creează fișierul și, iată, următoarea solicitare îl preia cu succes. După ștergerea acestuia prin DELETE, fișierul lipsește din nou.

Eroare la procesare

Există șase locuri în codul serverului de fișiere în care redirecționăm excepțiile când nu știm cum să gestionăm erorile. Deoarece excepțiile nu sunt transmise automat funcțiilor de apel invers, ci sunt transmise acestora ca argumente, acestea trebuie gestionate individual de fiecare dată. Acest lucru anulează beneficiul gestionării excepțiilor, și anume capacitatea de a gestiona erorile la nivel central.

Ce se întâmplă când ceva de fapt aruncă o excepție în sistem? Nu folosim blocuri try, așa că va fi trecut în partea de sus a stivei de apeluri. În Node, acest lucru face ca programul să se termine și să imprime informațiile de excepție (împreună cu o urmărire a stivei) la ieșirea standard.

Prin urmare, serverul nostru se va prăbuși atunci când există probleme în cod - spre deosebire de problemele cu asincronia, care vor fi transmise ca argumente funcției de apel. Dacă trebuie să gestionăm toate excepțiile care apar în timpul procesării unei cereri, astfel încât să trimitem cu exactitate un răspuns, trebuie să adăugăm blocuri try/catch în fiecare callback.

Asta e rău. Multe programe Node sunt scrise pentru a utiliza cât mai puțină gestionare a excepțiilor, ceea ce înseamnă că, dacă apare o excepție, programul nu o poate gestiona și, prin urmare, trebuie să se blocheze.

O altă abordare este folosirea promisiunilor, care au fost descrise în Capitolul 17. Acestea captează excepțiile aruncate de funcțiile de apel invers și le transmit drept erori. În Node, puteți încărca biblioteca de promisiune și o puteți utiliza pentru a gestiona apeluri asincrone. Puține biblioteci Node integrează promisiuni, dar sunt de obicei destul de simplu de împachetat. Excelentul modul „promise” de la NPM conține o funcție numită denodeify, care preia o funcție asincronă precum fs.readFile și o convertește într-o funcție care returnează o promisiune.

Var Promise = require("promisiune"); var fs = require("fs"); var readFile = Promise.denodeify(fs.readFile); readFile("fișier.txt", "utf8").then(funcție(conținut) ( console.log("Fișierul conține: " + conținut); ), function(eroare) ( console.log("Nu s-a putut citi fișierul : " + eroare); ));

Pentru comparație, am scris o altă versiune a unui server de fișiere folosind promises, care poate fi găsită la eloquentjavascript.net/code/file_server_promises.js. Este mai curat, deoarece funcțiile pot returna acum rezultate în loc să atribuie apeluri inverse, iar excepțiile sunt transmise implicit.

Voi cita câteva rânduri de acolo pentru a demonstra diferența de stiluri.

Obiectul fsp folosit în cod conține variante ale funcțiilor fs cu promisiuni împachetate folosind Promise.denodeify. Obiectul returnat de la handlerul de metodă, cu proprietățile codului și corpului, devine rezultatul final al lanțului de promisiuni și este folosit pentru a determina ce răspuns să trimită clientului.

Metode.GET = function(cale) ( return inspectPath(path).then(function(stats) ( if (!stats) // Nu există return (cod: 404, body: "Fișier nu a fost găsit"); altfel dacă ( stats.isDirectory()) return fsp.readdir(cale).then(function(fișiere) ( return (cod: 200, body: files.join("\n")); ) else return (cod: 200, tip: require("mime").lookup(cale), body: fs.createReadStream(cale)); funcția inspectPath(cale) ( return fsp.stat(path).then(null, function(error) (dacă (error.code == "ENOENT") return null; else throw error; )); )

Funcția inspectPath este un simplu wrapper în jurul fs.stat care se ocupă de cazul în care un fișier nu este găsit. În acest caz, înlocuim eroarea cu succes returnând null. Toate celelalte erori pot fi transmise. Când promisiunea returnată de la acești handleri se întrerupe, serverul răspunde cu codul 500.

Concluzie

Node este un sistem excelent, simplu, care vă permite să rulați JavaScript în afara browserului. A fost conceput inițial pentru a funcționa într-o rețea, pentru a juca rolul unui nod în rețea. Dar vă permite să faceți o mulțime de lucruri și, dacă vă place să programați în JavaScript, automatizarea sarcinilor zilnice cu Node funcționează grozav.

NPM oferă biblioteci pentru tot ceea ce vă puteți gândi (și chiar pentru unele lucruri pe care nu le aveți) și vă permite să le descărcați și să le instalați cu o comandă simplă. Node vine, de asemenea, cu un set de module încorporate, inclusiv „fs” pentru lucrul cu sistemul de fișiere și „http” pentru rularea serverelor HTTP și efectuarea de solicitări HTTP.

Toate intrările și ieșirile din Node se fac asincron, cu excepția cazului în care utilizați o variantă sincronă explicit a funcției, cum ar fi fs.readFileSync. Furnizați funcții de apel invers, iar Node le apelează la momentul potrivit când se termină operațiunile I/O.

Exerciții

Și din nou de acord asupra conținutului
În capitolul 17, primul exercițiu a fost crearea unor solicitări către eloquentjavascript.net/author care solicitau diferite tipuri de conținut prin trecerea diferitelor antete Accept.

Faceți-o din nou folosind funcția http.request a Node. Solicitați cel puțin tipurile text/plain, text/html și application/json. Amintiți-vă că anteturile cererii pot fi transmise ca obiect în proprietatea antete, primul argument pentru http.request.

Tipăriți conținutul fiecărui răspuns.

Repararea scurgerilor

Pentru a simplifica accesul la fișiere, am lăsat serverul să ruleze pe computerul meu, în directorul /home/marijn/public. Într-o zi am descoperit că cineva avea acces la toate parolele mele pe care le-am stocat în browser. Ce s-a întâmplat?

Dacă acest lucru nu vă este clar, amintiți-vă de funcția urlToPath, care a fost definită astfel:

Funcția urlToPath(url) ( var cale = require("url").parse(url).pathname; return "." + decodeURIComponent(cale); )

Acum amintiți-vă că căile transmise funcției „fs” pot fi relative. Acestea pot conține calea „../” către directorul de sus. Ce se întâmplă dacă clientul trimite solicitări la adrese URL precum următoarele:

myhostname :8000/../.config/config/google-chrome/Default/Web%20Data
myhostname:8000/../.ssh/id_dsa
numele gazdă:8000/../../../etc/passwd

Schimbați funcția urlToPath pentru a rezolva această problemă. Vă rugăm să rețineți că pe Windows Node permite atât barele oblice înainte, cât și barele oblice inverse pentru a specifica căile.

De asemenea, meditați asupra faptului că odată ce expuneți un sistem brut la Internet, erorile din sistem pot fi folosite împotriva dvs. și a computerului dvs.

Crearea directoarelor
Deși metoda DELETE funcționează și la ștergerea directoarelor (prin fs.rmdir), serverul nu oferă încă capacitatea de a crea directoare.

Adăugați suport pentru metoda MKCOL, care ar trebui să creeze un director prin fs.mkdir. MKCOL nu este o metodă HTTP de bază, dar există chiar în acest scop în standardul WebDAV, care conține extensii la HTTP pentru a permite folosirea acesteia pentru a scrie resurse, în loc să le citească.

Loc public pe web
Deoarece serverul de fișiere servește orice fișiere și chiar returnează antetul tip Content-Type, acesta poate fi folosit pentru a difuza un site web. Deoarece permite oricui să ștergă și să înlocuiască fișiere, acesta ar fi un site interesant - unul care poate fi modificat, corupt și șters de oricine poate crea o solicitare HTTP validă. Dar tot ar fi un site web.

Scrieți o pagină HTML simplă cu un fișier JavaScript simplu. Plasați-le într-un director deservit de server și deschideți-le într-un browser.

Apoi, ca exercițiu avansat, combinați tot ce ați învățat din carte pentru a construi o interfață mai ușor de utilizat pentru modificarea unui site web din site-ul propriu-zis.

Utilizați un formular HTML (Capitolul 18) pentru a edita fișierele care alcătuiesc site-ul, permițând utilizatorului să le actualizeze pe server prin solicitări HTTP, așa cum este descris în Capitolul 17.

Începeți cu un fișier pe care îl puteți edita. Apoi faceți-o astfel încât să puteți selecta fișierul de editat. Profitați de faptul că serverul nostru de fișiere returnează liste de fișiere atunci când sunt solicitate de un director.

Nu modificați fișierele direct în codul serverului de fișiere - dacă faceți o greșeală, probabil că veți deteriora acele fișiere. Lucrați într-un director care nu este accesibil din exterior și copiați-le acolo după testare.

Dacă computerul tău se conectează direct la Internet, fără firewall, router sau alte dispozitive, poți invita un prieten pe site-ul tău. Pentru a verifica, accesați whatismyip.com, copiați adresa IP în bara de adrese și adăugați:8000 pentru a selecta portul dorit. Dacă vă aflați pe site-ul dvs., acesta este disponibil pentru vizualizarea tuturor.

Salutare tuturor! În acest articol vom continua să înțelegem platforma NodeJS si vorbeste despre obiect global.

Ar trebui să fiți deja familiarizați cu acest concept. Când scriem javascript cod în browser, apoi folosim obiectul global fereastră. ÎN NodeJS există și un obiect global și se numește simplu Global.

Precum și fereastră, Global ne permite să folosim unele proprietăți și metode încorporate de oriunde în cod. Să ne uităm la exemple.

Probabil una dintre cele mai cunoscute metode, care, apropo, există și în obiectul global browser fereastră- Acest console.log(). O poti scrie asa:

Și codul va afișa textul între paranteze pe consola dumneavoastră.

O altă metodă binecunoscută care vă permite să efectuați o anumită acțiune după un timp specificat:

// Executați codul în 7 secunde (7000 milisecunde)
setTimeout(funcție() (
console.log ("Bună ziua, lume!");
}, 7000);

Cred că nu este greu de ghicit asta dacă există setTimeout(), atunci trebuie să existe setInterval().

// Va afișa „Bună, lume” în fiecare secundă
setInterval(funcție() (
console.log ("Bună ziua, lume!");
}, 1000);

NodeJS vă permite să primiți câteva informații utile de la sistem. De exemplu, puteți afla calea completă către folderul în care vă aflați în prezent folosind proprietatea globală a obiectului __dirname.

Console.log(__dirname);

Dacă doriți să obțineți și numele fișierului în care este executat codul, puteți scrie următoarele.

Într-un nod, puteți seta variabile globale printr-un obiect „global” sau „GLOBAL”:

GLOBAL._ = require("subliniere"); // dar „nu ar trebui” să faci asta! (vezi nota de mai jos)

sau mai util...

GLOBAL.window = GLOBAL; // ca în browser

Din sursa nodului puteți vedea că sunt aliasuri unul pentru celălalt:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = global;

În codul de mai sus, „acest” este contextul global. Cu modulul commonJS (pe care îl folosește nodul), acest „obiect” din interiorul modulului (adică „codul tău”) NU este contextul global. Pentru dovada acestui lucru, vedeți mai jos unde am aruncat „acest” obiect și apoi uriașul obiect „GLOBAL”.

Console.log("\nACEST:"); console.log(aceasta); console.log("\nGLOBAL:"); console.log(global); /* iese... ACEST: {} GLOBAL: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT: 2 ), ( Int32BYTES_PER_ELEMENT:_32 BYTES_PER_ELEMENT:_3) PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , proces: ( EventEmitter: , titlu: "nod", assert: , versiune: "v0.6.5", _tickCallback: , moduleLoadList: [ „Evaluări de legare”, „Evaluări de legare”, „Evenimente NativeModule”, „Buffer NativeModule”, „Buffer de legare”, „Afirmare NativeModule”, „Util NativeModule”, „Calea NativeModule”, „Modulul NativeModule”, „ NativeModule fs”, „Legarea fs”, „Constante de legare”, „Fluxul NativeModule”, „Consola NativeModule”, „Legarea tty_wrap”, „NativeModule tty”, „NativeModule net”, „Tronometre NativeModule”, „Legarea timer_wrap”, „ NativeModule _linklist" ], versiuni: ( nod: "0.6.5", v8: "3.6.6.11", ares: "1.7.5-DEV", uv: "0.6", openssl: "0.9.8n"), nextTick : , stdout: , arch: „x64”, stderr: , platformă: „darwin”, argv: [ „nod”, „/workspace/zd/zgap/darwin-js/index.js” ], stdin: , env: ( TERM_PROGRAM: "iTerm.app", "COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET": "/tmp/launch-nNl1vo/ServiceProcessSocket:m",/:" TERMSHELLSocket:m",/:"/" , TMPDIR: „/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/”, Apple_PubSub_Socket_Render: „/tmp/launch-9Ga0PT/Render”, UTILIZATOR: „ddopson”, COMMAND_MODE: „SOCKSH:_00Hmp”, „SOCK:_00Htp”, „SOCK:_00Hmp”, lansați -sD905b/Listeners", __CF_USER_TEXT_ENCODING: "0x12D732E7:0:0", PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/ X11 /bin”, PWD: „/workspace/zd/zgap/darwin-js”, LANG: „en_US.UTF-8”, ITERM_PROFILE: „Implicit”, SHLVL: „1”, COLORFGBG: „7;0”, HOME : „/Utilizatori/ddopson”, ITERM_SESSION_ID: „w0t0p0”, LOGNAME: „ddopson”, DISPLAY: „/tmp/launch-l9RQXI/org.x:0”, OLDPWD: „/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , ieșire: , pid: 10321, caracteristici: ( depanare: fals, uv: adevărat, ipv6: adevărat, tls_npn: fals, tls_sni: adevărat, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , debug: , eroare: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , moștenește: , _kill: , _byteLength: , mainModule: ( id: ". ", exportă: (), părinte: null, nume fișier: "/workspace/zd/zgap/darwin-js/index.js", încărcat: fals, ieșit: fals, copii: , căi: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInterval: , clearInterval: , clearInterval consola: , fereastra: , navigator: () ) */

**Notă: În ceea ce privește setarea „GLOBAL._”, în general, ar trebui să faceți doar var _ = require ("subliniere"); . Da, faci asta în fiecare fișier care folosește caractere de subliniere, la fel ca în Java, importi com.foo.bar; . Acest lucru face mai ușor să determinați ce face codul dvs., deoarece legăturile dintre fișiere sunt „explicite”. Ușor enervant, dar bun. .... Aceasta este o predică.

Există o excepție de la fiecare regulă. Am avut exact un caz în care trebuia să setez „GLOBAL._”. Cream un sistem pentru definirea fișierelor „config” care erau în mare parte JSON, dar „scrise în JS” pentru a adăuga puțin mai multă flexibilitate. Nu existau instrucțiuni „require” în astfel de fișiere de configurare, dar am vrut ca acestea să aibă acces la subliniere (întregul sistem se baza pe modele de subliniere și subliniere), așa că aș seta „GLOBAL._” înainte de a evalua „config”. Deci da, pentru fiecare regulă există o excepție undeva. Dar ai un motiv întemeiat, nu doar „M-am săturat să scriu „require”, așa că vreau să încalc convenția”.

Într-un nod, puteți seta variabile globale printr-un obiect „global” sau „GLOBAL”:

GLOBAL._ = require("subliniere"); // dar „nu ar trebui” să faci asta! (vezi nota de mai jos)

sau mai util...

GLOBAL.window = GLOBAL; // ca în browser

Din sursa nodului puteți vedea că sunt aliasuri unul pentru celălalt:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = global;

În codul de mai sus, „acest” este contextul global. Cu modulul commonJS (pe care îl folosește nodul), acest „obiect” din interiorul modulului (adică „codul tău”) NU este contextul global. Pentru dovada acestui lucru, vedeți mai jos unde am aruncat „acest” obiect și apoi uriașul obiect „GLOBAL”.

Console.log("\nACEST:"); console.log(aceasta); console.log("\nGLOBAL:"); console.log(global); /* iese... ACEST: {} GLOBAL: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT: 2 ), ( Int32BYTES_PER_ELEMENT:_32 BYTES_PER_ELEMENT:_3) PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , proces: ( EventEmitter: , titlu: "nod", assert: , versiune: "v0.6.5", _tickCallback: , moduleLoadList: [ „Evaluări de legare”, „Evaluări de legare”, „Evenimente NativeModule”, „Buffer NativeModule”, „Buffer de legare”, „Afirmare NativeModule”, „Util NativeModule”, „Calea NativeModule”, „Modulul NativeModule”, „ NativeModule fs”, „Legarea fs”, „Constante de legare”, „Fluxul NativeModule”, „Consola NativeModule”, „Legarea tty_wrap”, „NativeModule tty”, „NativeModule net”, „Tronometre NativeModule”, „Legarea timer_wrap”, „ NativeModule _linklist" ], versiuni: ( nod: "0.6.5", v8: "3.6.6.11", ares: "1.7.5-DEV", uv: "0.6", openssl: "0.9.8n"), nextTick : , stdout: , arch: „x64”, stderr: , platformă: „darwin”, argv: [ „nod”, „/workspace/zd/zgap/darwin-js/index.js” ], stdin: , env: ( TERM_PROGRAM: "iTerm.app", "COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET": "/tmp/launch-nNl1vo/ServiceProcessSocket:m",/:" TERMSHELLSocket:m",/:"/" , TMPDIR: „/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/”, Apple_PubSub_Socket_Render: „/tmp/launch-9Ga0PT/Render”, UTILIZATOR: „ddopson”, COMMAND_MODE: „SOCKSH:_00Hmp”, „SOCK:_00Htp”, „SOCK:_00Hmp”, lansați -sD905b/Listeners", __CF_USER_TEXT_ENCODING: "0x12D732E7:0:0", PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/ X11 /bin”, PWD: „/workspace/zd/zgap/darwin-js”, LANG: „en_US.UTF-8”, ITERM_PROFILE: „Implicit”, SHLVL: „1”, COLORFGBG: „7;0”, HOME : „/Utilizatori/ddopson”, ITERM_SESSION_ID: „w0t0p0”, LOGNAME: „ddopson”, DISPLAY: „/tmp/launch-l9RQXI/org.x:0”, OLDPWD: „/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , ieșire: , pid: 10321, caracteristici: ( depanare: fals, uv: adevărat, ipv6: adevărat, tls_npn: fals, tls_sni: adevărat, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , debug: , eroare: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , moștenește: , _kill: , _byteLength: , mainModule: ( id: ". ", exportă: (), părinte: null, nume fișier: "/workspace/zd/zgap/darwin-js/index.js", încărcat: fals, ieșit: fals, copii: , căi: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInterval: , clearInterval: , clearInterval consola: , fereastra: , navigator: () ) */

**Notă: În ceea ce privește setarea „GLOBAL._”, în general, ar trebui să faceți doar var _ = require ("subliniere"); Da, faci asta în fiecare fișier care folosește caracterul de subliniere, la fel ca în Java importi com.foo.bar; Acest lucru face mai ușor să determinați ce face codul dvs., deoarece legăturile dintre fișiere sunt „explicite”. Ușor enervant, dar bun. Aceasta este o predică.

Există o excepție de la fiecare regulă. Am avut exact un caz în care trebuia să setez „GLOBAL._”. Cream un sistem pentru definirea fișierelor „config” care erau în mare parte JSON, dar „scrise în JS” pentru a adăuga puțin mai multă flexibilitate. Nu existau instrucțiuni „require” în astfel de fișiere de configurare, dar am vrut ca acestea să aibă acces la subliniere (întregul sistem se baza pe modele de subliniere și subliniere), așa că aș seta „GLOBAL._” înainte de a evalua „config”. Deci da, pentru fiecare regulă există o excepție undeva. Dar ai un motiv întemeiat, nu doar „M-am săturat să tastez”, așa că vreau să încalc acordul”.

și mi s-a spus că pot seta variabilele la domeniul global, lăsând var.

Asta nu merge pentru mine.

Necesită ("subliniere");

Nu face _ disponibil pentru fișierele necesare. Pot instala app.set și îl pot folosi în altă parte.

Poate cineva să confirme că acest lucru ar trebui să funcționeze? Mulțumesc.



 


Citit:



Opriți telefonul mobil în timpul zborului

Opriți telefonul mobil în timpul zborului

Băieți, ne punem suflet în site. Îți mulțumesc că ai dezvăluit această frumusețe. Mulțumim pentru inspirație și frisoane. Alăturați-vă nouă pe Facebook și...

Numărul de telefon de asistență Kyivstar sau cum să apelați operatorul Informații suplimentare despre contactarea biroului de asistență

Numărul de telefon de asistență Kyivstar sau cum să apelați operatorul Informații suplimentare despre contactarea biroului de asistență

Uneori, gestionarea problemelor legate de comunicațiile mobile pe cont propriu poate fi destul de problematică. De exemplu, aflați ce opțiuni sunt pe numărul...

Roșu coloană levitantă Viitorul în care sunt posibile astfel de inovații tehnice a sosit deja

Roșu coloană levitantă Viitorul în care sunt posibile astfel de inovații tehnice a sosit deja

Acest dispozitiv poate fi folosit ca difuzor pentru orice sursă audio, fie că este un telefon sau un laptop. Dar ceea ce face coloana specială nu este...

Ce este mineritul criptomonedelor în termeni simpli?

Ce este mineritul criptomonedelor în termeni simpli?

Nu vom înțelege ce este criptomoneda și când a fost inventată prima criptomonedă. Să trecem direct la elementele de bază ale mineritului. Criptomonede pentru minerit...

feed-image RSS