Διαφήμιση

Σπίτι - Antivirus
Καθολικές μεταβλητές Node js. Nodejs βασικά

Σε έναν κόμβο, μπορείτε να ορίσετε καθολικές μεταβλητές μέσω ενός αντικειμένου "καθολικό" ή "GLOBAL":

GLOBAL._ = απαιτείται ("υπογράμμιση"); // αλλά "δεν" πρέπει να το κάνετε αυτό! (δείτε τη σημείωση παρακάτω)

ή πιο χρήσιμο...

GLOBAL.window = GLOBAL; // όπως στο πρόγραμμα περιήγησης

Από την πηγή κόμβου μπορείτε να δείτε ότι είναι ψευδώνυμα μεταξύ τους:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = παγκόσμιος;

Στον παραπάνω κώδικα, "αυτό" είναι το παγκόσμιο πλαίσιο. Με τη λειτουργική μονάδα commonJS (την οποία χρησιμοποιεί ο κόμβος), αυτό το "αντικείμενο" μέσα στη λειτουργική μονάδα (δηλαδή ο "κωδικός σας") ΔΕΝ είναι το καθολικό πλαίσιο. Για απόδειξη αυτού, δείτε παρακάτω πού εκτοξεύω "αυτό" το αντικείμενο και μετά το γιγάντιο αντικείμενο "GLOBAL".

Console.log("\nTHIS:"); console.log(this); console.log("\nGLOBAL:"); console.log(global); /* έξοδοι ... ΑΥΤΟ: {} ΠΑΓΚΟΣΜΙΑ: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT:) int32Array: ( BYTES_ PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , process: ( EventEmitter: , τίτλος: "node", assert: , έκδοση: "v0.6.5", _tickCall , moduleLoadList: [ "Binding evals", "Binding natives", "NativeModule events", "NativeModule buffer", "Binding buffer", "NativeModule assert", "NativeModule util", "NativeModule path", "NativeModule module", " NativeModule fs", "Binding fs", "Binding σταθερές", "NativeModule stream", "NativeModule console", "Binding tty_wrap", "NativeModule tty", "NativeModule net", "NativeModule timers", "Binding timer_wrap", " NativeModule _linklist" ], εκδόσεις: ( node: "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: , πλατφόρμα: "darwin", argv: [ "node", "/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-nNl1SHSket", "/tmp/launch-nNl1SHSket", " , TMPDIR: "/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/", Apple_PubSub_Socket_Render: "/tmp/launch-9Ga0PT/Render", USER: "ddopson", COMMAND_SH: launch -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: "Προεπιλογή", SHLVL: "1", COLORFGBG: "7;0", HOME : "/Users/ddopson", ITERM_SESSION_ID: "w0t0p0", LOGNAME: "ddopson", DISPLAY: "/tmp/launch-l9RQXI/org.x:0", OLDPWD: "/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , exit: , pid: 10321, χαρακτηριστικά: ( debug: false, uv: true, ipv6: true, tls_npn: false, tls_sni: true, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , εντοπισμός σφαλμάτων: , σφάλμα: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , κληρονομεί: , _kill: , _byteLength: , mainModule: ( id: ". ", εξάγει: (), γονικό: null, όνομα αρχείου: "/workspace/zd/zgap/darwin-js/index.js", φορτωμένο: false, έξοδος: false, παιδιά: , διαδρομές: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInvalterout: , clearInvalterout: κονσόλα: , παράθυρο: , πλοηγός: () ) */

**Σημείωση: Όσον αφορά τη ρύθμιση "GLOBAL._", σε γενικές γραμμές θα πρέπει απλώς να κάνετε var _ = require("υπογράμμιση"); Ναι, το κάνετε αυτό σε κάθε αρχείο που χρησιμοποιεί την υπογράμμιση, όπως ακριβώς στην Java εισάγετε το com.foo.bar. Αυτό διευκολύνει τον προσδιορισμό του τι κάνει ο κώδικάς σας, επειδή οι σύνδεσμοι μεταξύ των αρχείων είναι "σαφής". Ελαφρώς ενοχλητικό, αλλά καλό. Αυτό είναι κήρυγμα.

Υπάρχει μια εξαίρεση σε κάθε κανόνα. Είχα ακριβώς ένα παράδειγμα όπου έπρεπε να ρυθμίσω το "GLOBAL._". Δημιουργούσα ένα σύστημα για τον ορισμό αρχείων "config" που ήταν κυρίως JSON, αλλά ήταν "γραμμένα σε JS" για να προσθέσω λίγη περισσότερη ευελιξία. Δεν υπήρχαν δηλώσεις "απαιτείται" σε τέτοια αρχεία διαμόρφωσης, αλλά ήθελα να έχουν πρόσβαση στην υπογράμμιση (ΟΛΟΚΛΗΡΟ το σύστημα βασίστηκε σε μοτίβα υπογράμμισης και υπογράμμισης), επομένως θα έβαζα "GLOBAL._" πριν αξιολογήσω το "config". Οπότε ναι, για κάθε κανόνα υπάρχει κάπου μια εξαίρεση. Αλλά έχετε έναν καλό λόγο, όχι απλώς «βαρέθηκα να πληκτρολογώ», οπότε θέλω να σπάσω τη συμφωνία».

Ένας μαθητής ρώτησε: «Οι παλιοί προγραμματιστές χρησιμοποιούσαν μόνο απλούς υπολογιστές και προγραμματίζονταν χωρίς γλώσσες, αλλά έφτιαχναν όμορφα προγράμματα. Γιατί χρησιμοποιούμε πολύπλοκους υπολογιστές και γλώσσες προγραμματισμού;» Ο Φου-Τζου απάντησε: «Οι παλιοί χτίστες χρησιμοποιούσαν μόνο ξύλα και πηλό, αλλά έφτιαχναν όμορφες καλύβες».

Master Yuan-Ma, "Book of Programming"

Μέχρι στιγμής, έχετε μάθει JavaScript και τη χρησιμοποιείτε σε ένα μόνο περιβάλλον: το πρόγραμμα περιήγησης. Σε αυτό το κεφάλαιο και στο επόμενο, θα παρουσιάσουμε εν συντομία το Node.js, ένα πρόγραμμα που σας επιτρέπει να χρησιμοποιείτε δεξιότητες JavaScript εκτός του προγράμματος περιήγησης. Με αυτό μπορείτε να γράψετε τα πάντα, από βοηθητικά προγράμματα γραμμής εντολών έως δυναμικούς διακομιστές HTTP.

Αυτά τα κεφάλαια επικεντρώνονται στη διδασκαλία των σημαντικών ιδεών που απαρτίζουν το Node.js και έχουν σχεδιαστεί για να σας παρέχουν αρκετές πληροφορίες που θα σας επιτρέψουν να γράψετε χρήσιμα προγράμματα στο πλαίσιο. Δεν προσπαθούν να είναι ολοκληρωμένες αναφορές για το Node.

Θα μπορούσατε να γράψετε και να εκτελέσετε τον κώδικα από τα προηγούμενα κεφάλαια απευθείας στο πρόγραμμα περιήγησης, αλλά ο κώδικας από αυτό το κεφάλαιο γράφτηκε για το Node και δεν θα λειτουργήσει στο πρόγραμμα περιήγησης.

Εάν θέλετε να εκτελέσετε τον κώδικα σε αυτό το κεφάλαιο αμέσως, ξεκινήστε εγκαθιστώντας το Node από το nodejs.org για το λειτουργικό σας σύστημα. Επίσης σε αυτόν τον ιστότοπο θα βρείτε τεκμηρίωση για το Node και τις ενσωματωμένες μονάδες του.

Εισαγωγή

Ένα από τα πιο δύσκολα προβλήματα κατά τη σύνταξη συστημάτων που επικοινωνούν μέσω δικτύου είναι ο χειρισμός της εισόδου και της εξόδου. Ανάγνωση και εγγραφή δεδομένων προς και από το δίκτυο, το δίσκο και άλλες συσκευές. Η μετακίνηση δεδομένων απαιτεί χρόνο και ο σωστός σχεδιασμός για αυτήν τη δραστηριότητα μπορεί να επηρεάσει σημαντικά τον χρόνο απόκρισης του συστήματος για αιτήματα χρηστών ή δικτύου.

Στην παραδοσιακή επεξεργασία εισόδου και εξόδου, μια συνάρτηση όπως το readFile ξεκινά την ανάγνωση του αρχείου και επιστρέφει μόνο όταν το αρχείο έχει διαβαστεί πλήρως. Αυτό ονομάζεται σύγχρονη I/O (είσοδος/έξοδος).

Το Node σχεδιάστηκε για να κάνει την ασύγχρονη I/O ευκολότερη και ευκολότερη στη χρήση. Έχουμε ήδη δει ασύγχρονες διεπαφές, όπως το αντικείμενο του προγράμματος περιήγησης XMLHttpRequest, που συζητείται στο Κεφάλαιο 17. Μια τέτοια διεπαφή επιτρέπει στο σενάριο να συνεχίσει να εκτελείται ενώ η διεπαφή κάνει τη δουλειά της και καλεί μια συνάρτηση επανάκλησης όταν τελειώσει. Έτσι λειτουργούν όλα τα I/O στο Node.

Το JavaScript ταιριάζει εύκολα σε ένα σύστημα όπως το Node. Αυτή είναι μια από τις λίγες γλώσσες που δεν έχει ενσωματωμένο σύστημα I/O. Έτσι, η JavaScript ταιριάζει εύκολα στη μάλλον εκκεντρική προσέγγιση του Node στην είσοδο/εξόδου και δεν καταλήγει να δημιουργεί δύο διαφορετικά συστήματα εισόδου και εξόδου. Το 2009, κατά την ανάπτυξη του Node, οι άνθρωποι χρησιμοποιούσαν ήδη I/O βάσει κλήσης στο πρόγραμμα περιήγησης, έτσι η κοινότητα γύρω από τη γλώσσα ήταν συνηθισμένη σε ένα ασύγχρονο στυλ προγραμματισμού.

Ασύγχρονη

Θα προσπαθήσω να δείξω τη διαφορά στις σύγχρονες και ασύγχρονες προσεγγίσεις στο I/O με ένα μικρό παράδειγμα, όπου ένα πρόγραμμα πρέπει να λάβει δύο πόρους από το Διαδίκτυο και στη συνέχεια να κάνει κάτι με τα δεδομένα.

Σε ένα σύγχρονο περιβάλλον, ο προφανής τρόπος επίλυσης του προβλήματος είναι να κάνετε διαδοχικά ερωτήματα. Αυτή η μέθοδος έχει ένα μείον - το δεύτερο αίτημα θα ξεκινήσει μόνο αφού ολοκληρωθεί το πρώτο. Ο συνολικός χρόνος δεν θα είναι μικρότερος από το άθροισμα του χρόνου για την επεξεργασία δύο αιτημάτων. Πρόκειται για μια αναποτελεσματική χρήση του υπολογιστή, ο οποίος θα είναι σε αδράνεια τις περισσότερες φορές κατά τη μεταφορά δεδομένων μέσω του δικτύου.

Η λύση στο πρόβλημα σε ένα σύγχρονο σύστημα είναι η εκκίνηση πρόσθετων νημάτων ελέγχου εκτέλεσης προγράμματος (τα έχουμε ήδη συζητήσει στο Κεφάλαιο 14). Ένα δεύτερο νήμα μπορεί να εκτελέσει ένα δεύτερο αίτημα και στη συνέχεια και τα δύο νήματα θα περιμένουν να επιστραφεί το αποτέλεσμα, μετά από το οποίο θα συγχρονιστούν εκ νέου για να συγκλίνει η εργασία σε ένα μόνο αποτέλεσμα.

Στο διάγραμμα, οι παχιές γραμμές υποδεικνύουν τον κανονικό χρόνο λειτουργίας του προγράμματος και οι λεπτές γραμμές τον χρόνο αναμονής I/O. Στο σύγχρονο μοντέλο, ο χρόνος που δαπανάται για I/O περιλαμβάνεται στο χρονοδιάγραμμα καθενός από τα νήματα. Στην ασύγχρονη, η ενεργοποίηση μιας ενέργειας μέσω εισόδου/εξόδου οδηγεί σε διακλάδωση της γραμμής χρόνου. Το νήμα που εκκίνησε το I/O συνεχίζει την εκτέλεση και το I/O εκτελείται παράλληλα, κάνοντας μια επανάκληση συνάρτησης μετά την ολοκλήρωση.

Ροή προγράμματος για σύγχρονη και ασύγχρονη I/O

Ένας άλλος τρόπος έκφρασης αυτής της διαφοράς: στο σύγχρονο μοντέλο, η αναμονή για το τέλος του I/O είναι σιωπηρή, αλλά στο ασύγχρονο μοντέλο, είναι ρητή και βρίσκεται υπό τον άμεσο έλεγχό μας. Αλλά ο ασυγχρονισμός λειτουργεί και με τους δύο τρόπους. Διευκολύνει την έκφραση μη γραμμικών προγραμμάτων, αλλά δυσκολεύει την έκφραση προγραμμάτων ευθείας γραμμής.

Στο Κεφάλαιο 17, έθιξα ήδη το γεγονός ότι οι επανακλήσεις εισάγουν πολύ θόρυβο και κάνουν ένα πρόγραμμα λιγότερο οργανωμένο. Το αν αυτή η προσέγγιση είναι γενικά καλή ιδέα είναι συζητήσιμο. Σε κάθε περίπτωση, χρειάζεται χρόνος για να το συνηθίσεις.

Αλλά για ένα σύστημα που βασίζεται σε JavaScript, θα έλεγα ότι η χρήση ασυγχρονισμού με επανάκληση έχει νόημα. Ένα από τα δυνατά σημεία της JavaScript είναι η απλότητα και η προσπάθεια προσθήκης πολλαπλών νημάτων σε ένα πρόγραμμα θα οδηγούσε σε μεγάλη πολυπλοκότητα. Αν και οι επανακλήσεις δεν κάνουν τον κώδικα απλό, η ιδέα πίσω από αυτές είναι πολύ απλή και ωστόσο αρκετά ισχυρή ώστε να σας επιτρέπει να γράφετε διακομιστές ιστού υψηλής απόδοσης.

εντολή κόμβου

Όταν το Node.js είναι εγκατεστημένο στο σύστημά σας, έχετε ένα πρόγραμμα που ονομάζεται node που εκτελεί αρχεία JavaScript. Ας υποθέσουμε ότι έχετε ένα αρχείο hello.js με τον ακόλουθο κώδικα:

Var message = "Γεια σου κόσμο"; console.log(message);

Μπορείτε να εκτελέσετε το πρόγραμμά σας από τη γραμμή εντολών:

$node hello.js Γεια σου κόσμο

Η μέθοδος console.log στο Node λειτουργεί με τον ίδιο τρόπο όπως στο πρόγραμμα περιήγησης. Εμφανίζει ένα κομμάτι κειμένου. Αλλά στο Node, το κείμενο εκτυπώνεται σε τυπική έξοδο και όχι στην κονσόλα JavaScript στο πρόγραμμα περιήγησης.

Εάν εκτελείτε κόμβο χωρίς αρχείο, θα σας δώσει μια συμβολοσειρά ερωτήματος στην οποία μπορείτε να γράψετε κώδικα JavaScript και να λάβετε το αποτέλεσμα.

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

Η μεταβλητή διεργασίας, όπως και η κονσόλα, είναι διαθέσιμη παγκοσμίως στο Node. Παρέχει διάφορους τρόπους επιθεώρησης και χειρισμού ενός προγράμματος. Η μέθοδος εξόδου τερματίζει τη διαδικασία και μπορεί να μεταβιβαστεί ένας κωδικός κατάστασης εξόδου από το πρόγραμμα, ο οποίος λέει στο πρόγραμμα που εκκίνησε τον κόμβο (στην περίπτωση αυτή, το κέλυφος) εάν το πρόγραμμα εξήλθε επιτυχώς (κωδικός μηδέν) ή απέτυχε (οποιοσδήποτε άλλος αριθμός).

Για να αποκτήσετε πρόσβαση στα ορίσματα της γραμμής εντολών που μεταβιβάστηκαν στο πρόγραμμα, μπορείτε να διαβάσετε τον πίνακα συμβολοσειρών process.argv. Περιλαμβάνει επίσης το όνομα της εντολής κόμβου και το όνομα του σεναρίου σας, επομένως η λίστα ορισμάτων ξεκινά από το ευρετήριο 2. Εάν το αρχείο showargv.js περιέχει μόνο μια δήλωση console.log(process.argv), μπορείτε να την εκτελέσετε ως εξής :

$ node showargv.js one --and two ["node", "/home/marijn/showargv.js", "one", "--and", "two"]

Όλες οι τυπικές καθολικές μεταβλητές JavaScript - Array, Math, JSON, είναι επίσης διαθέσιμες στο περιβάλλον Node. Αλλά δεν υπάρχει καμία λειτουργικότητα που να σχετίζεται με το πρόγραμμα περιήγησης, όπως έγγραφο ή ειδοποίηση.

Το αντικείμενο καθολικού εύρους, που ονομάζεται παράθυρο στο πρόγραμμα περιήγησης, ονομάζεται πιο ουσιαστικά καθολικό στον Κόμβο.

Ενότητες

Εκτός από μερικές αναφερόμενες μεταβλητές, όπως η κονσόλα και η διαδικασία, το Node διατηρεί ελάχιστη λειτουργικότητα στο καθολικό εύρος. Για να αποκτήσετε πρόσβαση στις υπόλοιπες ενσωματωμένες δυνατότητες, πρέπει να αποκτήσετε πρόσβαση στο σύστημα μονάδων.

Το σύστημα CommonJS, με βάση τη συνάρτηση απαίτησης, περιγράφηκε στο Κεφάλαιο 10. Αυτό το σύστημα είναι ενσωματωμένο στο Node και χρησιμοποιείται για τη φόρτωση των πάντων, από ενσωματωμένες και ληφθείσες βιβλιοθήκες έως αρχεία που αποτελούν μέρη του προγράμματός σας.

Όταν καλείτε το απαιτούμενο κόμβο, πρέπει να μετατρέψετε τη δεδομένη συμβολοσειρά σε όνομα αρχείου. Οι διαδρομές που ξεκινούν με "/", "./" ή "../" μετατρέπονται σε διαδρομές σε σχέση με την τρέχουσα. "./" σημαίνει τον τρέχοντα κατάλογο, "../" σημαίνει τον παραπάνω κατάλογο και "/" σημαίνει τον ριζικό κατάλογο του συστήματος αρχείων. Εάν ζητήσετε "./world/world" από το αρχείο /home/marijn/elife/run.js, το Node θα προσπαθήσει να φορτώσει το αρχείο /home/marijn/elife/world/world.js. Η επέκταση .js μπορεί να παραλειφθεί.

Όταν περάσει μια συμβολοσειρά που δεν φαίνεται να είναι σχετική ή απόλυτη διαδρομή, θεωρείται ότι είναι είτε μια ενσωματωμένη λειτουργική μονάδα είτε μια λειτουργική μονάδα εγκατεστημένη στον κατάλογο node_modules. Για παράδειγμα, το request("fs") θα σας δώσει μια ενσωματωμένη λειτουργική μονάδα για εργασία με το σύστημα αρχείων και το require("elife") θα προσπαθήσει να φορτώσει τη βιβλιοθήκη από το node_modules/elife/. Η τυπική μέθοδος για την εγκατάσταση βιβλιοθηκών είναι η χρήση NPM, στην οποία θα επανέλθω αργότερα.

Για να το δείξουμε, ας φτιάξουμε ένα απλό έργο δύο αρχείων. Το πρώτο θα ονομάζεται main.js και θα ορίζει ένα σενάριο που καλείται από τη γραμμή εντολών, σχεδιασμένο να παραμορφώνει τις συμβολοσειρές.

Var garble = απαιτώ("./garble"); // Ο δείκτης 2 περιέχει το πρώτο όρισμα προγράμματος από τη γραμμή εντολών var argument = process.argv; console.log(garble(argument));

Το αρχείο garble.js ορίζει μια βιβλιοθήκη παραμόρφωσης συμβολοσειρών που μπορεί να χρησιμοποιηθεί τόσο από το πρόγραμμα γραμμής εντολών που καθορίσατε προηγουμένως όσο και από άλλα σενάρια που χρειάζονται άμεση πρόσβαση στη συνάρτηση αλλοίωσης.

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

Η αντικατάσταση του module.exports αντί της προσθήκης ιδιοτήτων σε αυτό, μας επιτρέπει να εξάγουμε μια συγκεκριμένη τιμή από μια λειτουργική μονάδα. Σε αυτήν την περίπτωση, το αποτέλεσμα του αιτήματος της ενότητας μας θα είναι η ίδια η συνάρτηση παραμόρφωσης.

Η συνάρτηση χωρίζει μια συμβολοσειρά σε χαρακτήρες χρησιμοποιώντας τη διαίρεση με μια κενή συμβολοσειρά και, στη συνέχεια, αντικαθιστά όλους τους χαρακτήρες με άλλους με έναν κωδικό 5 μονάδες υψηλότερο. Στη συνέχεια, ενώνει το αποτέλεσμα πίσω σε μια συμβολοσειρά.

Τώρα μπορούμε να καλέσουμε το εργαλείο μας:

$ node main.js JavaScript Of(fXhwnuy

Εγκατάσταση μέσω NPM

Το NPM, που αναφέρεται εν συντομία στο Κεφάλαιο 10, είναι ένα διαδικτυακό αποθετήριο λειτουργικών μονάδων JavaScript, πολλά από τα οποία είναι γραμμένα ειδικά για το Node. Όταν εγκαθιστάτε το Node στον υπολογιστή σας, λαμβάνετε ένα πρόγραμμα npm που παρέχει μια βολική διεπαφή σε αυτό το αποθετήριο.

Για παράδειγμα, μία από τις μονάδες NPM ονομάζεται figlet και μετατρέπει το κείμενο σε "τέχνη ASCII", σχέδια που αποτελούνται από χαρακτήρες κειμένου. Δείτε πώς να το εγκαταστήσετε:

$ npm εγκατάσταση 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 προστατευμένο] node_modules/figlet $ node > var figlet = require("figlet"); > figlet.text("Hello world!", function(error, data) ( if (error) console.error(error); else console.log(data); )); _ _ _ _ _ _ _ | | | | ___| | | ___ __ _____ _ __| | __| | | | |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| "__| |/ _` | | | _ | __/ | | (_) | \ V V / (_) | | | | (_| |_| |_| |_|\___|_|_|\ ___/ \_/\_/ \___/|_|_|\__,_(_)

Μετά την εκτέλεση της εγκατάστασης npm, το NPM θα δημιουργήσει έναν κατάλογο node_modules. Μέσα σε αυτό θα υπάρχει ένας κατάλογος figlet που περιέχει τη βιβλιοθήκη. Όταν ξεκινάμε το node και καλούμε το require("figlet"), η βιβλιοθήκη φορτώνεται και μπορούμε να καλέσουμε τη μέθοδο κειμένου της για να εκτυπώσουμε μεγάλα, φανταχτερά γράμματα.

Αυτό που είναι ενδιαφέρον είναι ότι αντί να επιστρέφει απλώς μια συμβολοσειρά που περιέχει κεφαλαία γράμματα, το figlet.text δέχεται μια συνάρτηση επανάκλησης στην οποία μεταβιβάζει το αποτέλεσμα. Περνάει επίσης ένα άλλο όρισμα εκεί, το σφάλμα, το οποίο θα περιέχει ένα αντικείμενο σφάλματος σε περίπτωση σφάλματος και μηδενικό σε περίπτωση επιτυχίας.

Αυτή η αρχή λειτουργίας υιοθετείται στο Node. Για να δημιουργήσετε γράμματα, το figlet πρέπει να διαβάσει ένα αρχείο από το δίσκο που περιέχει γράμματα. Η ανάγνωση ενός αρχείου είναι μια ασύγχρονη λειτουργία στο Node, επομένως το figlet.text δεν μπορεί να επιστρέψει το αποτέλεσμα αμέσως. Η ασύγχρονη είναι μεταδοτική - κάθε συνάρτηση που καλεί μια ασύγχρονη γίνεται η ίδια ασύγχρονη.

Το NPM είναι κάτι περισσότερο από απλή εγκατάσταση npm. Διαβάζει αρχεία package.json, τα οποία περιέχουν πληροφορίες JSON σχετικά με το πρόγραμμα ή τη βιβλιοθήκη, ιδίως σε ποιες βιβλιοθήκες βασίζεται. Εκτελώντας την εγκατάσταση npm στον κατάλογο που περιέχει ένα τέτοιο αρχείο θα εγκατασταθούν αυτόματα όλες οι εξαρτήσεις και με τη σειρά τους οι εξαρτήσεις τους. Το εργαλείο npm χρησιμοποιείται επίσης για τη φιλοξενία βιβλιοθηκών στο διαδικτυακό αποθετήριο NPM, ώστε άλλα άτομα να μπορούν να τα βρουν, να τα κατεβάσουν και να τα χρησιμοποιήσουν.

Δεν θα υπεισέλθουμε περαιτέρω σε λεπτομέρειες σχετικά με τη χρήση του NPM. Δείτε το npmjs.org για τεκμηρίωση σχετικά με την αναζήτηση βιβλιοθήκης.

μονάδα συστήματος αρχείων

Μία από τις πιο δημοφιλείς ενσωματωμένες μονάδες Node είναι η λειτουργική μονάδα "fs", η οποία σημαίνει "σύστημα αρχείων". Η μονάδα παρέχει λειτουργικότητα για εργασία με αρχεία και καταλόγους.

Για παράδειγμα, υπάρχει μια συνάρτηση readFile που διαβάζει ένα αρχείο και πραγματοποιεί επανάκληση με τα περιεχόμενα του αρχείου.

Var fs = απαιτείται ("fs"); fs.readFile("file.txt", "utf8", function(error, text) ( if (error) throw error; console.log("Και το αρχείο περιείχε:", κείμενο); ));

Το δεύτερο όρισμα για το readFile καθορίζει την κωδικοποίηση χαρακτήρων με την οποία θα μετατραπούν τα περιεχόμενα του αρχείου σε συμβολοσειρά. Το κείμενο μπορεί να μετατραπεί σε δυαδικά δεδομένα με πολλούς τρόπους, αλλά ο νεότερος είναι το UTF-8. Εάν δεν έχετε λόγο να πιστεύετε ότι το αρχείο περιέχει κείμενο σε διαφορετική κωδικοποίηση, μπορείτε να μεταβιβάσετε με ασφάλεια την παράμετρο "utf8". Εάν δεν καθορίσετε μια κωδικοποίηση, το Node θα σας δώσει τα δυαδικά κωδικοποιημένα δεδομένα ως αντικείμενο buffer και όχι ως συμβολοσειρά. Αυτό είναι ένα αντικείμενο που μοιάζει με πίνακα που περιέχει byte από ένα αρχείο.

Var fs = απαιτείται ("fs"); fs.readFile("file.txt", function(error, buffer) ( if (error) throw error; console.log("Το αρχείο περιείχε ", buffer.length, " bytes.", "First byte:", buffer ));

Μια παρόμοια λειτουργία, το writeFile, χρησιμοποιείται για την εγγραφή ενός αρχείου στο δίσκο.

Var fs = απαιτούν ("fs"); fs.writeFile("graffiti.txt", "Node was here", function(err) ( if (err) console.log("Τίποτα δεν λειτούργησε και να γιατί:", err); else console.log("Επιτυχής εγγραφή Όλοι είναι ελεύθεροι."));

Δεν χρειάζεται να ορίσετε την κωδικοποίηση εδώ, επειδή το writeFile υποθέτει ότι εάν του δοθεί μια συμβολοσειρά για να γράψει, και όχι ένα αντικείμενο buffer, τότε θα πρέπει να εξάγεται ως κείμενο με την προεπιλεγμένη κωδικοποίηση του UTF-8.

Η ενότητα "fs" περιέχει πολλά χρήσιμα πράγματα: η συνάρτηση readdir επιστρέφει μια λίστα αρχείων σε έναν κατάλογο ως μια σειρά από συμβολοσειρές, το stat θα επιστρέψει πληροφορίες σχετικά με ένα αρχείο, θα μετονομάσει ένα αρχείο, θα αποσυνδέσει διαγραφές κ.λπ. Δείτε την τεκμηρίωση στο nodejs.org

Πολλές συναρτήσεις fs έχουν και σύγχρονες και ασύγχρονες επιλογές. Για παράδειγμα, υπάρχει μια σύγχρονη έκδοση της συνάρτησης readFile που ονομάζεται readFileSync.

Var fs = απαιτείται ("fs"); console.log(fs.readFileSync("file.txt", "utf8"));

Οι σύγχρονες συναρτήσεις είναι πιο εύχρηστες και πιο χρήσιμες για απλά σενάρια όπου η προστιθέμενη ταχύτητα μιας ασύγχρονης μεθόδου δεν είναι σημαντική. Αλλά σημειώστε ότι ενώ εκτελείται η σύγχρονη ενέργεια, το πρόγραμμά σας σταματά εντελώς. Εάν χρειάζεται να ανταποκριθεί στις εισαγωγές χρήστη ή σε άλλα προγράμματα μέσω του δικτύου, η αναμονή για σύγχρονη I/O προκαλεί ενοχλητικές καθυστερήσεις.

Μονάδα HTTP

Μια άλλη κύρια ενότητα είναι το "http". Παρέχει λειτουργικότητα για τη δημιουργία διακομιστών HTTP και αιτημάτων HTTP.

Εδώ είναι όλα όσα χρειάζεστε για να ξεκινήσετε έναν απλό διακομιστή HTTP:

Var http = απαιτείται ("http"); var server = http.createServer(function( αίτημα, απάντηση) ( answer.writeHead(200, ("Content-Type": "text/html")); answer.write("

Γειά σου!

Ζητήσατε " + request.url + "

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

Εκτελώντας το σενάριο στον υπολογιστή σας, μπορείτε να κατευθύνετε το πρόγραμμα περιήγησής σας στο localhost:8000/hello, δημιουργώντας έτσι ένα αίτημα στον διακομιστή. Θα απαντήσει με μια μικρή σελίδα HTML.

Η συνάρτηση που μεταβιβάζεται ως όρισμα στον createServer καλείται κάθε φορά που επιχειρείται σύνδεση με τον διακομιστή. Οι μεταβλητές αιτήματος και απόκρισης είναι αντικείμενα που αντιπροσωπεύουν δεδομένα εισόδου και εξόδου. Το πρώτο περιέχει πληροφορίες σχετικά με το αίτημα, για παράδειγμα η ιδιότητα url περιέχει τη διεύθυνση URL αιτήματος.

Για να στείλετε κάτι πίσω, χρησιμοποιούνται οι μέθοδοι του αντικειμένου απόκρισης. Το πρώτο, writeHead, γράφει τις κεφαλίδες απόκρισης (βλ. Κεφάλαιο 17). Του δίνετε έναν κωδικό κατάστασης (σε αυτήν την περίπτωση 200 για το "OK") και ένα αντικείμενο που περιέχει τις τιμές της κεφαλίδας. Εδώ λέμε στον πελάτη ότι πρέπει να περιμένει για ένα έγγραφο HTML.

Στη συνέχεια έρχεται το σώμα απάντησης (το ίδιο το έγγραφο), που αποστέλλεται μέσω answer.write. Αυτή η μέθοδος μπορεί να κληθεί πολλές φορές εάν θέλετε να στείλετε την απάντηση σε κομμάτια, για παράδειγμα, ροή δεδομένων κατά την άφιξή τους. Τέλος, το answer.end σηματοδοτεί το τέλος της απάντησης.

Η κλήση του server.listen κάνει τον διακομιστή να ακούει για αιτήματα στη θύρα 8000. Επομένως, πρέπει να μεταβείτε στο localhost:8000 στο πρόγραμμα περιήγησής σας και όχι μόνο στο localhost (όπου η προεπιλεγμένη θύρα θα είναι 80).

Για να σταματήσετε ένα τέτοιο σενάριο Node, το οποίο δεν τερματίζεται αυτόματα επειδή περιμένει τα επόμενα συμβάντα (σε αυτήν την περίπτωση, συνδέσεις), πρέπει να πατήσετε Ctrl-C.

Ένας πραγματικός διακομιστής Ιστού κάνει πολύ περισσότερα από αυτά που περιγράφονται στο παράδειγμα. Εξετάζει τη μέθοδο αιτήματος (την ιδιότητα της μεθόδου) για να κατανοήσει ποια ενέργεια προσπαθεί να εκτελέσει ο πελάτης και τη διεύθυνση URL αιτήματος για να κατανοήσει σε ποιον πόρο πρέπει να εκτελεστεί αυτή η ενέργεια. Στη συνέχεια θα δείτε μια πιο προηγμένη έκδοση του διακομιστή.

Για να δημιουργήσουμε έναν πελάτη HTTP, μπορούμε να χρησιμοποιήσουμε τη συνάρτηση της ενότητας αιτήματος «http».

Var http = απαιτείται ("http"); var request = http.request(( hostname: "eloquentjavascript.net", διαδρομή: "/20_node.html", μέθοδος: "GET", κεφαλίδες: (Accept: "text/html") ), function(response) ( κονσόλα .log("Η υπηρεσία απάντησε με τον κωδικό ", answer.statusCode )); request.end();

Το πρώτο όρισμα αίτησης διαμορφώνει το αίτημα, δηλώνοντας στον Node με ποιον διακομιστή θα επικοινωνήσουμε, ποια διαδρομή θα ακολουθήσει το αίτημα, ποια μέθοδος να χρησιμοποιήσει κ.λπ. Το δεύτερο είναι η λειτουργία. που θα χρειαστεί να καλέσετε στο τέλος του αιτήματος. Αποστέλλεται ένα αντικείμενο απόκρισης, το οποίο περιέχει όλες τις πληροφορίες σχετικά με την απάντηση - για παράδειγμα, τον κωδικό κατάστασης.

Όπως το αντικείμενο απόκρισης του διακομιστή, το αντικείμενο που επιστρέφεται με αίτημα σάς επιτρέπει να μεταβιβάζετε δεδομένα με τη μέθοδο εγγραφής και να τερματίζετε το αίτημα με τη μέθοδο τερματισμού. Το παράδειγμα δεν χρησιμοποιεί εγγραφή επειδή τα αιτήματα GET δεν πρέπει να περιέχουν δεδομένα στο σώμα.

Για αιτήματα για ασφαλή URL (HTTPS), το Node προσφέρει τη λειτουργική μονάδα https, η οποία έχει τη δική της λειτουργία αιτήματος παρόμοια με το http.request.

Ρεύματα

Έχουμε δει δύο παραδείγματα ροών στα παραδείγματα HTTP - το αντικείμενο απόκρισης, στο οποίο μπορεί να γράψει ο διακομιστής και το αντικείμενο αίτησης, το οποίο επιστρέφεται από το http.request

Οι εγγράψιμες ροές είναι μια δημοφιλής έννοια στις διεπαφές Node. Όλα τα νήματα έχουν μια μέθοδο εγγραφής, η οποία μπορεί να περάσει μια συμβολοσειρά ή ένα αντικείμενο buffer. Η μέθοδος τέλους κλείνει τη ροή και εάν υπάρχει κάποιο όρισμα, θα εκτυπώσει ένα κομμάτι δεδομένων πριν κλείσει. Και στις δύο μεθόδους μπορεί να δοθεί μια συνάρτηση επανάκλησης μέσω ενός πρόσθετου ορίσματος, το οποίο θα καλέσουν όταν ολοκληρωθεί η εγγραφή ή η ροή κλείσει.

Είναι δυνατή η δημιουργία μιας ροής που οδηγεί σε ένα αρχείο χρησιμοποιώντας τη συνάρτηση fs.createWriteStream. Στη συνέχεια, μπορείτε να χρησιμοποιήσετε τη μέθοδο εγγραφής για να γράψετε στο αρχείο σε κομμάτια και όχι ως σύνολο, όπως στο fs.writeFile.

Οι αναγνώσιμες ροές θα είναι λίγο πιο περίπλοκες. Τόσο η μεταβλητή αιτήματος που μεταβιβάστηκε στη συνάρτηση επανάκλησης στον διακομιστή HTTP όσο και η μεταβλητή απόκρισης που μεταβιβάστηκε στον πελάτη HTTP είναι αναγνώσιμες ροές. (Ο διακομιστής διαβάζει το αίτημα και στη συνέχεια γράφει απαντήσεις και ο πελάτης γράφει το αίτημα και διαβάζει την απάντηση). Η ανάγνωση από μια ροή γίνεται μέσω χειριστών συμβάντων, όχι μέσω μεθόδων.

Τα αντικείμενα που δημιουργούν συμβάντα στο Node έχουν μια μέθοδο ενεργοποίησης, παρόμοια με τη μέθοδο addEventListener του προγράμματος περιήγησης. Του δίνετε ένα όνομα συμβάντος και μια συνάρτηση και καταχωρεί αυτή τη συνάρτηση έτσι ώστε να καλείται αμέσως όταν συμβεί το συμβάν.

Οι αναγνώσιμες ροές έχουν συμβάντα "δεδομένα" και "τέλος". Το πρώτο συμβαίνει όταν φθάνουν τα δεδομένα, το δεύτερο συμβαίνει με την ολοκλήρωση. Αυτό το μοντέλο είναι κατάλληλο για ροή δεδομένων που μπορούν να υποβληθούν σε άμεση επεξεργασία, ακόμη και αν δεν ληφθεί ολόκληρο το έγγραφο. Το αρχείο μπορεί να διαβαστεί ως ροή μέσω του fs.createReadStream.

Ο παρακάτω κώδικας δημιουργεί έναν διακομιστή που διαβάζει τα σώματα αιτημάτων και τα στέλνει πίσω ως ροή κειμένου με κεφαλαία.

Var http = απαιτείται ("http"); http.createServer(function( request, response) ( answer.writeHead(200, ("Content-Type": "text/plain")); request.on("data", function(chunk) ( answer.write(chunk .toString().toUpperCase());

Η μεταβλητή chunk που μεταβιβάζεται στον χειριστή δεδομένων θα είναι ένα δυαδικό buffer, το οποίο μπορεί να μετατραπεί σε συμβολοσειρά καλώντας τη μέθοδο toString, η οποία την αποκωδικοποιεί από την προεπιλεγμένη κωδικοποίηση (UTF-8).

Ο ακόλουθος κώδικας, όταν εκτελείται ταυτόχρονα με τον διακομιστή, θα στείλει ένα αίτημα στον διακομιστή και θα εκτυπώσει την απάντηση που ελήφθη:

Var http = απαιτείται ("http"); var request = http.request((όνομα κεντρικού υπολογιστή: "localhost", θύρα: 8000, μέθοδος: "POST"), function(response) ( answer.on("data", function(chunk) ( process.stdout.write(chunk .toString()); request.end("Hello server");

Το παράδειγμα γράφει στο process.stdout (την τυπική έξοδο της διεργασίας, που είναι μια εγγράψιμη ροή) αντί στο console.log. Δεν μπορούμε να χρησιμοποιήσουμε το console.log επειδή προσθέτει μια επιπλέον αλλαγή γραμμής μετά από κάθε κομμάτι κώδικα - δεν χρειάζεται εδώ.

Απλός διακομιστής αρχείων

Ας συνδυάσουμε τις νέες μας γνώσεις σχετικά με τους διακομιστές HTTP και την εργασία με το σύστημα αρχείων και ας χτίσουμε μια γέφυρα μεταξύ τους: έναν διακομιστή HTTP που παρέχει απομακρυσμένη πρόσβαση στα αρχεία. Υπάρχουν πολλές περιπτώσεις χρήσης για έναν τέτοιο διακομιστή. Επιτρέπει σε εφαρμογές web να αποθηκεύουν και να μοιράζονται δεδομένα ή μπορεί να δώσει σε μια ομάδα ατόμων πρόσβαση σε ένα σύνολο αρχείων.

Όταν αντιμετωπίζουμε τα αρχεία ως πόρους HTTP, οι μέθοδοι GET, PUT και DELETE μπορούν να χρησιμοποιηθούν για ανάγνωση, εγγραφή και διαγραφή αρχείων. Θα ερμηνεύσουμε τη διαδρομή στο αίτημα ως τη διαδρομή προς το αρχείο.

Δεν χρειάζεται να εκθέσουμε ολόκληρο το σύστημα αρχείων, επομένως θα ερμηνεύσουμε αυτές τις διαδρομές ως σχετικές με τον ριζικό κατάλογο και αυτός θα είναι ο κατάλογος εκκίνησης του σεναρίου. Εάν ξεκινήσω τον διακομιστή από το /home/marijn/public/ (ή C:\Users\marijn\public\ στα Windows), τότε ένα αίτημα στο /file.txt θα πρέπει να οδηγεί στο /home/marijn/public/file.txt ( ή C :\Users\marijn\public\file.txt).

Θα δημιουργήσουμε το πρόγραμμα σταδιακά, χρησιμοποιώντας το αντικείμενο μεθόδων για την αποθήκευση συναρτήσεων που χειρίζονται διαφορετικές μεθόδους HTTP.

Var http = απαιτούν ("http"), fs = απαιτούν ("fs"); var metoda = Object.create(null); http.createServer(function(αίτημα, απάντηση) ( συνάρτηση απάντηση (κωδικός, σώμα, τύπος) ( if (!type) type = "text/plain"; answer.writeHead(code, ("Content-Type": type)) if (body.pipe) body.pipe(response.end(body if (request.method) σε μεθόδους(urlToPath(request.url)), 405. "Μέθοδος " + request.method + "δεν επιτρέπεται )).listen(8000);

Αυτός ο κωδικός θα ξεκινήσει ο διακομιστής να επιστρέφει σφάλματα 405 - αυτός ο κωδικός χρησιμοποιείται για να υποδείξει ότι η ζητούμενη μέθοδος δεν υποστηρίζεται από τον διακομιστή.

Η συνάρτηση απόκρισης μεταβιβάζεται σε συναρτήσεις που χειρίζονται διαφορετικές μεθόδους και λειτουργεί ως επιστροφή κλήσης για την ολοκλήρωση του αιτήματος. Αποδέχεται έναν κωδικό κατάστασης HTTP, ένα σώμα και πιθανώς έναν τύπο περιεχομένου. Εάν το διερχόμενο σώμα είναι ένα αναγνώσιμο ρεύμα, θα έχει μια μέθοδο σωλήνα που χρησιμοποιείται για τη διέλευση ενός αναγνώσιμου ρεύματος σε ένα εγγράψιμο ρεύμα. Εάν όχι, υποτίθεται ότι είναι είτε μηδενικό (το σώμα είναι κενό) είτε μια συμβολοσειρά και στη συνέχεια μεταβιβάζεται απευθείας στη μέθοδο τελικής απόκρισης.

Για να λάβετε τη διαδρομή από μια διεύθυνση URL σε ένα αίτημα, η συνάρτηση urlToPath χρησιμοποιεί την ενσωματωμένη ενότητα "url" του Node για την ανάλυση της διεύθυνσης URL. Παίρνει ένα όνομα διαδρομής, κάτι σαν /file.txt, αποκωδικοποιεί για να αφαιρέσει %20 κωδικούς διαφυγής και εισάγει μια κύρια κουκκίδα για να πάρει τη διαδρομή σε σχέση με τον τρέχοντα κατάλογο.

Πιστεύετε ότι η συνάρτηση urlToPath δεν είναι ασφαλής; Εχεις δίκιο. Θα επανέλθουμε σε αυτό το θέμα στις ασκήσεις.

Θα σχεδιάσουμε τη μέθοδο GET για να επιστρέφει μια λίστα αρχείων κατά την ανάγνωση ενός καταλόγου και τα περιεχόμενα ενός αρχείου κατά την ανάγνωση ενός αρχείου.

Το πραγματικό ερώτημα είναι τι τύπο κεφαλίδας τύπου περιεχομένου πρέπει να επιστρέφουμε κατά την ανάγνωση ενός αρχείου. Δεδομένου ότι μπορεί να υπάρχει οτιδήποτε σε ένα αρχείο, ο διακομιστής δεν μπορεί απλώς να επιστρέψει τον ίδιο τύπο για όλους. Αλλά το NPM μπορεί να βοηθήσει σε αυτό. Η μονάδα mime (οι δείκτες τύπου περιεχομένου αρχείου όπως το κείμενο/απλό ονομάζονται επίσης τύποι MIME) γνωρίζει τον σωστό τύπο για έναν τεράστιο αριθμό επεκτάσεων αρχείων.

Εκτελώντας την ακόλουθη εντολή npm στον κατάλογο όπου ζει το σενάριο διακομιστή, μπορείτε να χρησιμοποιήσετε το require("mime") για να κάνετε ερώτημα στη βιβλιοθήκη τύπων.

$ npm εγκατάσταση mime npm http GET https://registry.npmjs.org/mime npm http 304 https://registry.npmjs.org/mime [email προστατευμένο] node_modules/mime

Όταν το ζητούμενο αρχείο δεν υπάρχει, ο σωστός κωδικός σφάλματος για αυτήν την περίπτωση είναι 404. Θα χρησιμοποιήσουμε το fs.stat για να επιστρέψουμε πληροφορίες στο αρχείο για να μάθουμε αν υπάρχει τέτοιο αρχείο και αν είναι κατάλογος.

Methods.GET = συνάρτηση(διαδρομή, απάντηση) ( fs.stat(διαδρομή, συνάρτηση(σφάλμα, στατιστικά) ( if (σφάλμα && error.code == "ENOENT") answer(404, "Το αρχείο δεν βρέθηκε"); αλλιώς εάν (σφάλμα) answer(500, error.toString()? ; else respond(200, files.join("\n"));

Επειδή τα ερωτήματα στο δίσκο χρειάζονται χρόνο, το fs.stat εκτελείται ασύγχρονα. Όταν το αρχείο δεν υπάρχει, το fs.stat θα μεταβιβάσει ένα αντικείμενο σφάλματος με την ιδιότητα κώδικα "ENOENT" στη συνάρτηση επανάκλησης. Θα ήταν ωραίο αν το Node όριζε διαφορετικούς τύπους σφαλμάτων για διαφορετικά σφάλματα, αλλά δεν το κάνει. Αντίθετα, βγάζει μπερδεμένους κώδικες τύπου Unix.

Θα εκδίδουμε όλα τα απροσδόκητα σφάλματα με τον κωδικό 500, υποδεικνύοντας ότι υπάρχει πρόβλημα στον διακομιστή - σε αντίθεση με τους κωδικούς που ξεκινούν με 4, οι οποίοι υποδεικνύουν πρόβλημα με το αίτημα. Σε ορισμένες περιπτώσεις αυτό δεν θα είναι απολύτως ακριβές, αλλά για ένα μικρό δείγμα προγράμματος θα είναι αρκετό.

Το αντικείμενο stats που επιστρέφεται από το fs.stat μας λέει τα πάντα για το αρχείο. Για παράδειγμα, το μέγεθος είναι το μέγεθος του αρχείου, το mtime είναι η ημερομηνία τροποποίησης. Εδώ πρέπει να μάθουμε αν πρόκειται για κατάλογο ή για κανονικό αρχείο - αυτό θα μας πει η μέθοδος isDirectory.

Για να διαβάσουμε μια λίστα αρχείων σε έναν κατάλογο, χρησιμοποιούμε το fs.readdir και μέσω μιας άλλης επανάκλησης, την επιστρέφουμε στον χρήστη. Για κανονικά αρχεία, δημιουργούμε μια αναγνώσιμη ροή μέσω του fs.createReadStream και τη μεταβιβάζουμε στην απάντηση, μαζί με τον τύπο περιεχομένου που παρήγαγε η μονάδα mime για αυτό το αρχείο.

Ο κωδικός χειρισμού DELETE θα είναι απλούστερος:

Methods.DELETE = συνάρτηση(διαδρομή, απάντηση) ( fs.stat(διαδρομή, συνάρτηση(σφάλμα, στατιστικά) ( if (error && error.code == "ENOENT") answer(204); else if (σφάλμα) answer(500 , error.toString()); else if (stats.isDirectory()) fs.rmdir(path, respondErrorOrNothing(respond));

Ίσως αναρωτιέστε γιατί η προσπάθεια διαγραφής ενός αρχείου που δεν υπάρχει επιστρέφει μια κατάσταση 204 αντί για σφάλμα. Μπορούμε να πούμε ότι όταν προσπαθείτε να διαγράψετε ένα ανύπαρκτο αρχείο, καθώς το αρχείο δεν υπάρχει πλέον, το αίτημα έχει ήδη εκτελεστεί. Το πρότυπο HTTP ενθαρρύνει τους ανθρώπους να υποβάλλουν ακατάλληλα αιτήματα, δηλαδή αιτήματα στα οποία η επανάληψη της ίδιας ενέργειας πολλές φορές δεν παράγει διαφορετικά αποτελέσματα.

Συνάρτηση answerErrorOrNothing(respond) ( return function(error) ( if (error) answer(500, error.toString()); else answer(204); ); )

Όταν η απόκριση HTTP δεν περιέχει δεδομένα, μπορείτε να χρησιμοποιήσετε τον κωδικό κατάστασης 204 ("χωρίς περιεχόμενο"). Επειδή πρέπει να παρέχουμε συναρτήσεις επανάκλησης που είτε αναφέρουν σφάλματα είτε επιστρέφουν μια απόκριση 204 σε διάφορες καταστάσεις, έγραψα μια ειδική συνάρτηση answerErrorOrNothing που δημιουργεί μια τέτοια επανάκληση.

Εδώ είναι ο χειριστής αιτημάτων PUT:

Methods.PUT = συνάρτηση(διαδρομή, απάντηση, αίτημα) ( var outStream = fs.createWriteStream(διαδρομή); outStream.on("σφάλμα", συνάρτηση(σφάλμα) ( answer(500, error.toString()); )); outStream.on("finish", function() ( answer(204); ));

Εδώ δεν χρειάζεται να ελέγξουμε την ύπαρξη του αρχείου - αν υπάρχει, απλώς θα το αντικαταστήσουμε. Και πάλι χρησιμοποιούμε σωλήνα για να μεταφέρουμε δεδομένα από μια ροή ανάγνωσης σε μια ροή εγγραφής, στην περίπτωσή μας από ένα αίτημα σε ένα αρχείο. Εάν το νήμα δεν μπορεί να δημιουργηθεί, δημιουργείται ένα συμβάν "σφάλμα", το οποίο αναφέρουμε στην απάντηση. Όταν τα δεδομένα μεταφερθούν επιτυχώς, ο σωλήνας θα κλείσει και τα δύο ρεύματα, προκαλώντας την πυροδότηση του συμβάντος «τελείωμα». Και μετά από αυτό μπορούμε να αναφέρουμε την επιτυχία με τον κωδικό 204.

Το πλήρες σενάριο διακομιστή είναι εδώ: eloquentjavascript.net/code/file_server.js. Μπορεί να γίνει λήψη και εκτέλεση μέσω του Node. Φυσικά, μπορεί να αλλάξει και να συμπληρωθεί για την επίλυση ασκήσεων ή πειραμάτων.

Το βοηθητικό πρόγραμμα γραμμής εντολών curl, που διατίθεται δημόσια σε συστήματα Unix, μπορεί να χρησιμοποιηθεί για τη δημιουργία αιτημάτων HTTP. Το παρακάτω απόσπασμα δοκιμάζει τον διακομιστή μας. Το –X χρησιμοποιείται για τον καθορισμό της μεθόδου αίτησης και το –d χρησιμοποιείται για να συμπεριλάβει το σώμα αιτήματος.

$ curl http://localhost:8000/file.txt Το αρχείο δεν βρέθηκε $ curl -X PUT -d γεια http://localhost:8000/file.txt $ curl http://localhost:8000/file.txt γεια $ curl -X DELETE http://localhost:8000/file.txt $ curl http://localhost:8000/file.txt Το αρχείο δεν βρέθηκε

Το πρώτο αίτημα για file.txt αποτυγχάνει επειδή το αρχείο δεν υπάρχει ακόμα. Το αίτημα PUT δημιουργεί το αρχείο και ιδού, το επόμενο αίτημα το ανακτά με επιτυχία. Μετά τη διαγραφή του μέσω DELETE, το αρχείο λείπει ξανά.

Σφάλμα επεξεργασίας

Υπάρχουν έξι σημεία στον κώδικα διακομιστή αρχείων όπου ανακατευθύνουμε εξαιρέσεις όταν δεν ξέρουμε πώς να χειριστούμε σφάλματα. Δεδομένου ότι οι εξαιρέσεις δεν μεταβιβάζονται αυτόματα στις συναρτήσεις επανάκλησης, αλλά μεταβιβάζονται σε αυτές ως ορίσματα, πρέπει να αντιμετωπίζονται μεμονωμένα κάθε φορά. Αυτό αναιρεί το όφελος του χειρισμού εξαιρέσεων, δηλαδή την ικανότητα διαχείρισης σφαλμάτων κεντρικά.

Τι συμβαίνει όταν κάτι δημιουργεί μια εξαίρεση στο σύστημα; Δεν χρησιμοποιούμε μπλοκ δοκιμής, επομένως θα περάσει στην κορυφή της στοίβας κλήσεων. Στο Node, αυτό προκαλεί τον τερματισμό του προγράμματος και την εκτύπωση των πληροφοριών εξαίρεσης (μαζί με ένα ίχνος στοίβας) σε τυπική έξοδο.

Επομένως, ο διακομιστής μας θα διακοπεί όταν υπάρχουν προβλήματα στον κώδικα - σε αντίθεση με προβλήματα με ασυγχρονισμό, τα οποία θα περάσουν ως ορίσματα στη συνάρτηση κλήσης. Εάν πρέπει να χειριστούμε όλες τις εξαιρέσεις που προκύπτουν κατά την επεξεργασία ενός αιτήματος, ώστε να στείλουμε με ακρίβεια μια απάντηση, πρέπει να προσθέσουμε μπλοκ try/catch σε κάθε επανάκληση.

Αυτό είναι κακό. Πολλά προγράμματα Node έχουν γραφτεί για να χρησιμοποιούν όσο το δυνατόν λιγότερο χειρισμό εξαιρέσεων, υπονοώντας ότι εάν παρουσιαστεί μια εξαίρεση, το πρόγραμμα δεν μπορεί να τη χειριστεί και επομένως πρέπει να διακοπεί.

Μια άλλη προσέγγιση είναι η χρήση υποσχέσεων, οι οποίες περιγράφηκαν στο Κεφάλαιο 17. Εντοπίζουν εξαιρέσεις που δημιουργούνται από συναρτήσεις επανάκλησης και τις μεταβιβάζουν ως σφάλματα. Στο Node, μπορείτε να φορτώσετε τη βιβλιοθήκη υποσχέσεων και να τη χρησιμοποιήσετε για να χειριστείτε ασύγχρονες κλήσεις. Λίγες βιβλιοθήκες Node ενσωματώνουν υποσχέσεις, αλλά συνήθως είναι αρκετά απλές στην αναδίπλωση. Η εξαιρετική ενότητα "promise" από το NPM περιέχει μια συνάρτηση που ονομάζεται denodeify, η οποία παίρνει μια ασύγχρονη συνάρτηση όπως το fs.readFile και τη μετατρέπει σε μια συνάρτηση που επιστρέφει μια υπόσχεση.

Var Promise = απαιτώ ("υπόσχεση"); var fs = require("fs"); var readFile = Promise.denodeify(fs.readFile); readFile("file.txt", "utf8").then(function(content) ( console.log("Το αρχείο περιείχε: " + περιεχόμενο); ), function(error) ( console.log("Αποτυχία ανάγνωσης του αρχείου : " + σφάλμα); ));

Για σύγκριση, έγραψα μια άλλη έκδοση ενός διακομιστή αρχείων χρησιμοποιώντας υποσχέσεις, τις οποίες μπορείτε να βρείτε στο eloquentjavascript.net/code/file_server_promises.js. Είναι πιο καθαρό γιατί οι συναρτήσεις μπορούν πλέον να επιστρέφουν αποτελέσματα αντί να εκχωρούν επανακλήσεις και οι εξαιρέσεις μεταβιβάζονται σιωπηρά.

Θα παραθέσω μερικές γραμμές από εκεί για να δείξω τη διαφορά στα στυλ.

Το αντικείμενο fsp που χρησιμοποιείται στον κώδικα περιέχει παραλλαγές των συναρτήσεων fs με υποσχέσεις τυλιγμένες χρησιμοποιώντας Promise.denodeify. Το αντικείμενο που επιστρέφεται από τον χειριστή μεθόδου, με τις ιδιότητες κώδικα και σώματος, γίνεται το τελικό αποτέλεσμα της αλυσίδας υποσχέσεων και χρησιμοποιείται για να καθοριστεί ποια απάντηση θα σταλεί στον πελάτη.

Methods.GET = function(path) ( return inspectPath(path).then(function(stats) ( if (!stats) // Δεν υπάρχει επιστροφή (κωδικός: 404, σώμα: "Το αρχείο δεν βρέθηκε"); αλλιώς εάν ( stats.isDirectory()) return fsp.readdir(path).then(function(files) ( return (code: 200, body: files.join("\n")); ) else return (κωδικός: 200, type: require("mime").lookup(path), body: fs.createReadStream(path)); συνάρτηση inspectPath(διαδρομή) ( return fsp.stat(path).then(null, function(error) ( if (error.code == "ENOENT") return null; else throw error; )); )

Η συνάρτηση inspectPath είναι ένα απλό περιτύλιγμα γύρω από το fs.stat που χειρίζεται την περίπτωση όταν δεν βρίσκεται ένα αρχείο. Σε αυτήν την περίπτωση, αντικαθιστούμε το σφάλμα με επιτυχία επιστρέφοντας μηδενικό. Όλα τα άλλα σφάλματα μπορούν να μεταδοθούν. Όταν η υπόσχεση που επιστράφηκε από αυτούς τους χειριστές σπάσει, ο διακομιστής αποκρίνεται με τον κωδικό 500.

Συμπέρασμα

Το Node είναι ένα εξαιρετικό, απλό σύστημα που σας επιτρέπει να εκτελείτε JavaScript εκτός του προγράμματος περιήγησης. Αρχικά σχεδιάστηκε για να λειτουργεί σε ένα δίκτυο, να παίζει το ρόλο ενός κόμβου στο δίκτυο. Αλλά σας επιτρέπει να κάνετε πολλά πράγματα και αν σας αρέσει ο προγραμματισμός σε JavaScript, η αυτοματοποίηση των καθημερινών εργασιών με το Node λειτουργεί εξαιρετικά.

Το NPM παρέχει βιβλιοθήκες για όλα όσα μπορείτε να σκεφτείτε (ακόμα και μερικά πράγματα που δεν έχετε) και σας επιτρέπει να τα κατεβάσετε και να τα εγκαταστήσετε με μια απλή εντολή. Το Node συνοδεύεται επίσης από ένα σύνολο ενσωματωμένων λειτουργικών μονάδων, όπως το "fs" για εργασία με το σύστημα αρχείων και το "http" για την εκτέλεση διακομιστών HTTP και την υποβολή αιτημάτων HTTP.

Όλες οι είσοδοι και έξοδοι στο Node γίνονται ασύγχρονα, εκτός εάν χρησιμοποιείτε μια ρητά σύγχρονη παραλλαγή της συνάρτησης, όπως το fs.readFileSync. Παρέχετε συναρτήσεις επανάκλησης και το Node τις καλεί την κατάλληλη στιγμή όταν τελειώνουν οι λειτουργίες I/O.

Γυμνάσια

Και πάλι συμφωνώντας στο περιεχόμενο
Στο Κεφάλαιο 17, η πρώτη άσκηση ήταν η δημιουργία αιτημάτων στο eloquentjavascript.net/author που ζητούσαν διαφορετικούς τύπους περιεχομένου περνώντας διαφορετικές κεφαλίδες Αποδοχή.

Κάντε το ξανά χρησιμοποιώντας τη συνάρτηση http.request του Node. Ζητήστε τουλάχιστον τους τύπους text/plain, text/html και application/json. Να θυμάστε ότι οι κεφαλίδες αιτημάτων μπορούν να μεταβιβαστούν ως αντικείμενο στην ιδιότητα κεφαλίδων, το πρώτο όρισμα στο http.request.

Εκτυπώστε τα περιεχόμενα κάθε απάντησης.

Επισκευή διαρροών

Για να απλοποιήσω την πρόσβαση στα αρχεία, άφησα τον διακομιστή να λειτουργεί στον υπολογιστή μου, στον κατάλογο /home/marijn/public. Μια μέρα ανακάλυψα ότι κάποιος είχε πρόσβαση σε όλους τους κωδικούς πρόσβασης που είχα αποθηκεύσει στο πρόγραμμα περιήγησης. Τι συνέβη?

Εάν αυτό δεν είναι σαφές σε εσάς, θυμηθείτε τη συνάρτηση urlToPath, η οποία ορίστηκε ως εξής:

Συνάρτηση urlToPath(url) ( var path = require("url").parse(url).pathname; return "." + decodeURIcomponent(path); )

Τώρα θυμηθείτε ότι οι διαδρομές που περνούν στη συνάρτηση "fs" μπορεί να είναι σχετικές. Μπορεί να περιέχουν τη διαδρομή "../" στον επάνω κατάλογο. Τι συμβαίνει εάν ο πελάτης στείλει αιτήματα σε διευθύνσεις URL όπως τα εξής:

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

Αλλάξτε τη συνάρτηση urlToPath για να επιλύσετε αυτό το ζήτημα. Λάβετε υπόψη ότι στον Κόμβο των Windows επιτρέπει τόσο τις εμπρός όσο και τις ανάστροφες κάθετες να καθορίσουν διαδρομές.

Επίσης, σκεφτείτε το γεγονός ότι μόλις εκθέσετε ένα ακατέργαστο σύστημα στο Διαδίκτυο, τα σφάλματα στο σύστημα μπορούν να χρησιμοποιηθούν εναντίον σας και του υπολογιστή σας.

Δημιουργία καταλόγων
Αν και η μέθοδος DELETE λειτουργεί επίσης κατά τη διαγραφή καταλόγων (μέσω fs.rmdir), ο διακομιστής δεν παρέχει ακόμη τη δυνατότητα δημιουργίας καταλόγων.

Προσθέστε υποστήριξη για τη μέθοδο MKCOL, η οποία θα πρέπει να δημιουργήσει έναν κατάλογο μέσω του fs.mkdir. Το MKCOL δεν είναι μια βασική μέθοδος HTTP, αλλά υπάρχει για αυτόν ακριβώς τον σκοπό στο πρότυπο WebDAV, το οποίο περιέχει επεκτάσεις στο HTTP για να του επιτρέψει να χρησιμοποιηθεί για τη σύνταξη πόρων και όχι απλώς για την ανάγνωσή τους.

Δημόσιος χώρος στον Ιστό
Δεδομένου ότι ο διακομιστής αρχείων εξυπηρετεί οποιαδήποτε αρχεία και επιστρέφει ακόμη και τη σωστή κεφαλίδα Τύπου περιεχομένου, μπορεί να χρησιμοποιηθεί για την εξυπηρέτηση ενός ιστότοπου. Δεδομένου ότι επιτρέπει σε οποιονδήποτε να διαγράψει και να αντικαταστήσει αρχεία, αυτός θα ήταν ένας ενδιαφέρον ιστότοπος - αυτός που μπορεί να τροποποιηθεί, να καταστραφεί και να διαγραφεί από οποιονδήποτε μπορεί να δημιουργήσει ένα έγκυρο αίτημα HTTP. Αλλά θα ήταν ακόμα ένας ιστότοπος.

Γράψτε μια απλή σελίδα HTML με ένα απλό αρχείο JavaScript. Τοποθετήστε τα σε έναν κατάλογο που εξυπηρετείται από τον διακομιστή και ανοίξτε τα σε ένα πρόγραμμα περιήγησης.

Στη συνέχεια, ως άσκηση για προχωρημένους, συνδυάστε όλα όσα έχετε μάθει από το βιβλίο για να δημιουργήσετε μια πιο φιλική προς το χρήστη διεπαφή για την τροποποίηση ενός ιστότοπου μέσα από τον ίδιο τον ιστότοπο.

Χρησιμοποιήστε μια φόρμα HTML (Κεφάλαιο 18) για να επεξεργαστείτε τα αρχεία που απαρτίζουν τον ιστότοπο, επιτρέποντας στον χρήστη να τα ενημερώσει στον διακομιστή μέσω αιτημάτων HTTP, όπως περιγράφεται στο Κεφάλαιο 17.

Ξεκινήστε με ένα αρχείο που μπορείτε να επεξεργαστείτε. Στη συνέχεια, κάντε το έτσι ώστε να μπορείτε να επιλέξετε το αρχείο που θέλετε να επεξεργαστείτε. Επωφεληθείτε από το γεγονός ότι ο διακομιστής αρχείων μας επιστρέφει λίστες αρχείων όταν ζητηθεί από έναν κατάλογο.

Μην αλλάζετε αρχεία απευθείας στον κώδικα διακομιστή αρχείων - εάν κάνετε λάθος, πιθανότατα θα καταστρέψετε αυτά τα αρχεία. Εργαστείτε σε έναν κατάλογο που δεν είναι προσβάσιμος από το εξωτερικό και αντιγράψτε τον εκεί μετά τη δοκιμή.

Εάν ο υπολογιστής σας συνδέεται απευθείας στο Διαδίκτυο, χωρίς τείχος προστασίας, δρομολογητή ή άλλες συσκευές, μπορείτε να προσκαλέσετε έναν φίλο στον ιστότοπό σας. Για έλεγχο, μεταβείτε στο whatismyip.com, αντιγράψτε τη διεύθυνση IP στη γραμμή διευθύνσεων και προσθέστε:8000 για να επιλέξετε τη θύρα που θέλετε. Εάν βρίσκεστε στον ιστότοπό σας, είναι διαθέσιμος για προβολή σε όλους.

Γεια σε όλους! Σε αυτό το άρθρο θα συνεχίσουμε να κατανοούμε την πλατφόρμα NodeJSκαι να μιλήσουμε για παγκόσμιο αντικείμενο.

Θα πρέπει να είστε ήδη εξοικειωμένοι με αυτήν την έννοια. Όταν γράφουμε javascriptκώδικα στο πρόγραμμα περιήγησης, στη συνέχεια χρησιμοποιούμε το καθολικό αντικείμενο παράθυρο. ΣΕ NodeJSυπάρχει και ένα παγκόσμιο αντικείμενο και απλά ονομάζεται Παγκόσμια.

Καθώς παράθυρο, Παγκόσμιαμας επιτρέπει να χρησιμοποιούμε ορισμένες ενσωματωμένες ιδιότητες και μεθόδους από οπουδήποτε στον κώδικα. Ας δούμε παραδείγματα.

Πιθανώς μια από τις πιο διάσημες μεθόδους, η οποία, παρεμπιπτόντως, υπάρχει επίσης στο παγκόσμιο αντικείμενο του προγράμματος περιήγησης παράθυρο- Αυτό console.log(). Μπορείτε να το γράψετε ως εξής:

Και ο κώδικας θα εμφανίσει το κείμενο που είναι γραμμένο σε αγκύλες στην κονσόλα σας.

Μια άλλη πολύ γνωστή μέθοδος που σας επιτρέπει να εκτελέσετε κάποια ενέργεια μετά από έναν καθορισμένο χρόνο:

// Εκτέλεση του κώδικα σε 7 δευτερόλεπτα (7000 χιλιοστά του δευτερολέπτου)
setTimeout(function() (
console.log("Γεια, κόσμο!");
}, 7000);

Νομίζω ότι δεν είναι δύσκολο να το μαντέψει κανείς αν υπάρχει setTimeout(), τότε πρέπει να υπάρχει setInterval().

// Θα εμφανίζει "Hello, world" κάθε δευτερόλεπτο
setInterval(function() (
console.log("Γεια, κόσμο!");
}, 1000);

NodeJSσας επιτρέπει να λαμβάνετε χρήσιμες πληροφορίες από το σύστημα. Για παράδειγμα, μπορείτε να μάθετε την πλήρη διαδρομή προς τον φάκελο στον οποίο βρίσκεστε αυτήν τη στιγμή χρησιμοποιώντας την ιδιότητα καθολικού αντικειμένου __dirname.

Console.log(__dirname);

Εάν θέλετε επίσης να λάβετε το όνομα του αρχείου όπου εκτελείται ο κώδικας, μπορείτε να γράψετε τα εξής.

Σε έναν κόμβο, μπορείτε να ορίσετε καθολικές μεταβλητές μέσω ενός αντικειμένου "καθολικό" ή "GLOBAL":

GLOBAL._ = απαιτείται ("υπογράμμιση"); // αλλά "δεν" πρέπει να το κάνετε αυτό! (δείτε τη σημείωση παρακάτω)

ή πιο χρήσιμο...

GLOBAL.window = GLOBAL; // όπως στο πρόγραμμα περιήγησης

Από την πηγή κόμβου μπορείτε να δείτε ότι είναι ψευδώνυμα μεταξύ τους:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = παγκόσμιος;

Στον παραπάνω κώδικα, "αυτό" είναι το παγκόσμιο πλαίσιο. Με τη λειτουργική μονάδα commonJS (την οποία χρησιμοποιεί ο κόμβος), αυτό το "αντικείμενο" μέσα στη λειτουργική μονάδα (δηλαδή ο "κωδικός σας") ΔΕΝ είναι το καθολικό πλαίσιο. Για απόδειξη αυτού, δείτε παρακάτω πού εκτοξεύω "αυτό" το αντικείμενο και μετά το γιγάντιο αντικείμενο "GLOBAL".

Console.log("\nTHIS:"); console.log(this); console.log("\nGLOBAL:"); console.log(global); /* έξοδοι ... ΑΥΤΟ: {} ΠΑΓΚΟΣΜΙΑ: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT:) int32Array: ( BYTES_ PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , process: ( EventEmitter: , τίτλος: "node", assert: , έκδοση: "v0.6.5", _tickCall , moduleLoadList: [ "Binding evals", "Binding natives", "NativeModule events", "NativeModule buffer", "Binding buffer", "NativeModule assert", "NativeModule util", "NativeModule path", "NativeModule module", " NativeModule fs", "Binding fs", "Binding σταθερές", "NativeModule stream", "NativeModule console", "Binding tty_wrap", "NativeModule tty", "NativeModule net", "NativeModule timers", "Binding timer_wrap", " NativeModule _linklist" ], εκδόσεις: ( node: "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: , πλατφόρμα: "darwin", argv: [ "node", "/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-nNl1SHSket", "/tmp/launch-nNl1SHSket", " , TMPDIR: "/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/", Apple_PubSub_Socket_Render: "/tmp/launch-9Ga0PT/Render", USER: "ddopson", COMMAND_SH: launch -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: "Προεπιλογή", SHLVL: "1", COLORFGBG: "7;0", HOME : "/Users/ddopson", ITERM_SESSION_ID: "w0t0p0", LOGNAME: "ddopson", DISPLAY: "/tmp/launch-l9RQXI/org.x:0", OLDPWD: "/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , exit: , pid: 10321, χαρακτηριστικά: ( debug: false, uv: true, ipv6: true, tls_npn: false, tls_sni: true, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , εντοπισμός σφαλμάτων: , σφάλμα: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , κληρονομεί: , _kill: , _byteLength: , mainModule: ( id: ". ", εξάγει: (), γονικό: null, όνομα αρχείου: "/workspace/zd/zgap/darwin-js/index.js", φορτωμένο: false, έξοδος: false, παιδιά: , διαδρομές: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInvalterout: , clearInvalterout: κονσόλα: , παράθυρο: , πλοηγός: () ) */

**Σημείωση: Όσον αφορά τη ρύθμιση "GLOBAL._", σε γενικές γραμμές θα πρέπει απλώς να κάνετε var _ = require("υπογράμμιση"); . Ναι, το κάνετε αυτό σε κάθε αρχείο που χρησιμοποιεί υπογράμμιση, όπως ακριβώς στην Java εισάγετε το com.foo.bar. . Αυτό διευκολύνει τον προσδιορισμό του τι κάνει ο κώδικάς σας, επειδή οι σύνδεσμοι μεταξύ των αρχείων είναι "σαφής". Ελαφρώς ενοχλητικό, αλλά καλό. .... Αυτό είναι κήρυγμα.

Υπάρχει μια εξαίρεση σε κάθε κανόνα. Είχα ακριβώς ένα παράδειγμα όπου έπρεπε να ρυθμίσω το "GLOBAL._". Δημιουργούσα ένα σύστημα για τον ορισμό αρχείων "config" που ήταν κυρίως JSON, αλλά ήταν "γραμμένα σε JS" για να προσθέσω λίγη περισσότερη ευελιξία. Δεν υπήρχαν δηλώσεις "απαιτείται" σε τέτοια αρχεία διαμόρφωσης, αλλά ήθελα να έχουν πρόσβαση στην υπογράμμιση (ΟΛΟΚΛΗΡΟ το σύστημα βασίστηκε σε μοτίβα υπογράμμισης και υπογράμμισης), επομένως θα έβαζα "GLOBAL._" πριν αξιολογήσω το "config". Οπότε ναι, για κάθε κανόνα υπάρχει κάπου μια εξαίρεση. Αλλά έχετε έναν καλό λόγο, όχι απλώς "Είμαι κουρασμένος να πληκτρολογώ "require", οπότε θέλω να σπάσω τη σύμβαση."

Σε έναν κόμβο, μπορείτε να ορίσετε καθολικές μεταβλητές μέσω ενός αντικειμένου "καθολικό" ή "GLOBAL":

GLOBAL._ = απαιτείται ("υπογράμμιση"); // αλλά "δεν" πρέπει να το κάνετε αυτό! (δείτε τη σημείωση παρακάτω)

ή πιο χρήσιμο...

GLOBAL.window = GLOBAL; // όπως στο πρόγραμμα περιήγησης

Από την πηγή κόμβου μπορείτε να δείτε ότι είναι ψευδώνυμα μεταξύ τους:

Node-v0.6.6/src/node.js:28:global = this; 128: global.GLOBAL = παγκόσμιος;

Στον παραπάνω κώδικα, "αυτό" είναι το παγκόσμιο πλαίσιο. Με τη λειτουργική μονάδα commonJS (την οποία χρησιμοποιεί ο κόμβος), αυτό το "αντικείμενο" μέσα στη λειτουργική μονάδα (δηλαδή ο "κωδικός σας") ΔΕΝ είναι το καθολικό πλαίσιο. Για απόδειξη αυτού, δείτε παρακάτω πού εκτοξεύω "αυτό" το αντικείμενο και μετά το γιγάντιο αντικείμενο "GLOBAL".

Console.log("\nTHIS:"); console.log(this); console.log("\nGLOBAL:"); console.log(global); /* έξοδοι ... ΑΥΤΟ: {} ΠΑΓΚΟΣΜΙΑ: ( ArrayBuffer: , Int8Array: ( BYTES_PER_ELEMENT: 1 ), Uint8Array: ( BYTES_PER_ELEMENT: 1 ), Int16Array: ( BYTES_PER_ELEMENT: 2 ), Uint16Array: ( BYTES_PER_ELEMENT:) int32Array: ( BYTES_ PER_ELEMENT: 4 ), Float32Array: ( BYTES_PER_ELEMENT: 4 ), Float64Array: ( BYTES_PER_ELEMENT: 8 ), DataView: , global: , process: ( EventEmitter: , τίτλος: "node", assert: , έκδοση: "v0.6.5", _tickCall , moduleLoadList: [ "Binding evals", "Binding natives", "NativeModule events", "NativeModule buffer", "Binding buffer", "NativeModule assert", "NativeModule util", "NativeModule path", "NativeModule module", " NativeModule fs", "Binding fs", "Binding σταθερές", "NativeModule stream", "NativeModule console", "Binding tty_wrap", "NativeModule tty", "NativeModule net", "NativeModule timers", "Binding timer_wrap", " NativeModule _linklist" ], εκδόσεις: ( node: "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: , πλατφόρμα: "darwin", argv: [ "node", "/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-nNl1SHSket", "/tmp/launch-nNl1SHSket", " , TMPDIR: "/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/", Apple_PubSub_Socket_Render: "/tmp/launch-9Ga0PT/Render", USER: "ddopson", COMMAND_SH: launch -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: "Προεπιλογή", SHLVL: "1", COLORFGBG: "7;0", HOME : "/Users/ddopson", ITERM_SESSION_ID: "w0t0p0", LOGNAME: "ddopson", DISPLAY: "/tmp/launch-l9RQXI/org.x:0", OLDPWD: "/workspace/zd/zgap/darwin- js /external", _: "./index.js"), openStdin: , exit: , pid: 10321, χαρακτηριστικά: ( debug: false, uv: true, ipv6: true, tls_npn: false, tls_sni: true, tls : true ), kill: , execPath: "/usr/local/bin/node", addListener: , _needTickCallback: , on: , removeListener: , reallyExit: , chdir: , εντοπισμός σφαλμάτων: , σφάλμα: , cwd: , watchFile: , umask : , getuid: , unwatchFile: , mixin: , setuid: , setgid: , createChildProcess: , getgid: , κληρονομεί: , _kill: , _byteLength: , mainModule: ( id: ". ", εξάγει: (), γονικό: null, όνομα αρχείου: "/workspace/zd/zgap/darwin-js/index.js", φορτωμένο: false, έξοδος: false, παιδιά: , διαδρομές: ), _debugProcess: , dlopen: , uptime: , memoryUsage: , uvCounters: , binding: ), GLOBAL: , root: , Buffer: ( poolSize: 8192, isBuffer: , byteLength: , _charsWritten: 8 ), setTimeout: , setInterval: , clearInvalterout: , clearInvalterout: κονσόλα: , παράθυρο: , πλοηγός: () ) */

**Σημείωση: Όσον αφορά τη ρύθμιση "GLOBAL._", σε γενικές γραμμές θα πρέπει απλώς να κάνετε var _ = require("υπογράμμιση"); Ναι, το κάνετε αυτό σε κάθε αρχείο που χρησιμοποιεί την υπογράμμιση, όπως ακριβώς στην Java εισάγετε το com.foo.bar. Αυτό διευκολύνει τον προσδιορισμό του τι κάνει ο κώδικάς σας, επειδή οι σύνδεσμοι μεταξύ των αρχείων είναι "σαφής". Ελαφρώς ενοχλητικό, αλλά καλό. Αυτό είναι κήρυγμα.

Υπάρχει μια εξαίρεση σε κάθε κανόνα. Είχα ακριβώς ένα παράδειγμα όπου έπρεπε να ρυθμίσω το "GLOBAL._". Δημιουργούσα ένα σύστημα για τον ορισμό αρχείων "config" που ήταν κυρίως JSON, αλλά ήταν "γραμμένα σε JS" για να προσθέσω λίγη περισσότερη ευελιξία. Δεν υπήρχαν δηλώσεις "απαιτείται" σε τέτοια αρχεία διαμόρφωσης, αλλά ήθελα να έχουν πρόσβαση στην υπογράμμιση (ΟΛΟΚΛΗΡΟ το σύστημα βασίστηκε σε μοτίβα υπογράμμισης και υπογράμμισης), επομένως θα έβαζα "GLOBAL._" πριν αξιολογήσω το "config". Οπότε ναι, για κάθε κανόνα υπάρχει κάπου μια εξαίρεση. Αλλά έχετε έναν καλό λόγο, όχι απλώς «βαρέθηκα να πληκτρολογώ», οπότε θέλω να σπάσω τη συμφωνία».

και μου είπαν ότι μπορούσα να ορίσω τις μεταβλητές στο καθολικό εύρος, αφήνοντας το var.

Αυτό δεν λειτουργεί για μένα.

Require ("υπογράμμιση");

Δεν καθιστά _ διαθέσιμο για απαιτούμενα αρχεία. Μπορώ να εγκαταστήσω το app.set και να το χρησιμοποιήσω αλλού.

Μπορεί κάποιος να επιβεβαιώσει ότι αυτό πρέπει να λειτουργήσει; Ευχαριστώ.



 


Ανάγνωση:



Απενεργοποιήστε το κινητό σας τηλέφωνο κατά τη διάρκεια της πτήσης

Απενεργοποιήστε το κινητό σας τηλέφωνο κατά τη διάρκεια της πτήσης

Παιδιά, βάζουμε την ψυχή μας στο site. Σας ευχαριστώ που αποκαλύπτετε αυτήν την ομορφιά. Ευχαριστούμε για την έμπνευση και την ψυχραιμία Ελάτε μαζί μας στο Facebook και...

Αριθμός τηλεφώνου υποστήριξης Kyivstar ή πώς να καλέσετε τον χειριστή Πρόσθετες πληροφορίες σχετικά με την επικοινωνία με το γραφείο βοήθειας

Αριθμός τηλεφώνου υποστήριξης Kyivstar ή πώς να καλέσετε τον χειριστή Πρόσθετες πληροφορίες σχετικά με την επικοινωνία με το γραφείο βοήθειας

Μερικές φορές η αντιμετώπιση θεμάτων που σχετίζονται με τις κινητές επικοινωνίες μόνοι σας μπορεί να είναι αρκετά προβληματική. Για παράδειγμα, μάθετε ποιες επιλογές υπάρχουν στον αριθμό...

Κόκκινη αιωρούμενη στήλη Το μέλλον στο οποίο είναι δυνατές τέτοιες τεχνικές καινοτομίες έχει ήδη φτάσει

Κόκκινη αιωρούμενη στήλη Το μέλλον στο οποίο είναι δυνατές τέτοιες τεχνικές καινοτομίες έχει ήδη φτάσει

Αυτή η συσκευή μπορεί να χρησιμοποιηθεί ως ηχείο για οποιαδήποτε πηγή ήχου, είτε πρόκειται για τηλέφωνο είτε για φορητό υπολογιστή. Αυτό όμως που κάνει τη στήλη ξεχωριστή δεν είναι...

Τι είναι η εξόρυξη κρυπτονομισμάτων με απλά λόγια;

Τι είναι η εξόρυξη κρυπτονομισμάτων με απλά λόγια;

Δεν θα καταλάβουμε τι είναι το κρυπτονόμισμα και πότε εφευρέθηκε το πρώτο κρυπτονόμισμα. Ας πάμε κατευθείαν στα βασικά της εξόρυξης. Κρυπτονομίσματα για εξόρυξη...

τροφοδοσία-εικόνα RSS