Πώς λειτουργεί ο βρόχος συμβάντων σε JavaScript;

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

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

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

Αυτό το άρθρο εστιάζει σε μία από τις πολύ σημαντικές αλλά σπάνια κατανοητές έννοιες ή όρους στο JavaScript. Το EVENT LOOP!.

Η εγγραφή ασύγχρονου κώδικα δεν μπορεί να αποφευχθεί στο JavaScript, αλλά γιατί σημαίνει πραγματικά ένας κώδικας που εκτελείται ασύγχρονα; δηλαδή The Event Loop

Προτού καταλάβουμε πώς λειτουργεί ο βρόχος συμβάντων, πρέπει πρώτα να καταλάβουμε τι είναι η ίδια η JavaScript και πώς λειτουργεί!

Τι είναι η JavaScript;

Πριν προχωρήσουμε, θα ήθελα να κάνουμε ένα βήμα πίσω στα πολύ βασικά. Τι είναι πραγματικά η JavaScript; Θα μπορούσαμε να ορίσουμε το JavaScript ως:

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

Περίμενε, τι είναι αυτό; Βιβλιώδης ορισμός; 🤔

Ας το αναλύσουμε!

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

Μονό νήμα

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

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

Πώς μπορεί η JavaScript να είναι μονονηματική και μη αποκλειστική ταυτόχρονα;

  Πώς να συνδέσετε ένα Samsung Galaxy Watch σε ένα νέο τηλέφωνο

Τι σημαίνει όμως αποκλεισμός;

Μη μπλοκάρισμα

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

Αλλά περιμένετε, είπα ότι η JavaScript εκτελείται σε ένα μόνο νήμα; Και είπα επίσης μη μπλοκάρισμα, που σημαίνει ότι η εργασία εκτελείται γρήγορα στη στοίβα κλήσεων; Αλλά πως??? Τι θα λέγατε όταν τρέχουμε χρονόμετρα; Βρόχοι;

Χαλαρώστε! Θα το μάθαμε σε λίγο 😉.

Ταυτόχρονος

Συγχρονισμός σημαίνει ότι ο κώδικας εκτελείται ταυτόχρονα από περισσότερα από ένα νήμα.

Εντάξει, τα πράγματα γίνονται πραγματικά Περίεργο τώρα, πώς μπορεί η JavaScript να είναι μονού νήματος και να είναι ταυτόχρονη; δηλαδή να εκτελεί τον κώδικά του με περισσότερα από ένα νήμα;

Ασύγχρονη

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

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

Πριν προχωρήσουμε, ας κάνουμε μια ανακεφαλαίωση των παραπάνω.

  • Η JavaScript είναι μονού νήματος
  • Η JavaScript δεν αποκλείει, δηλαδή οι αργές διεργασίες δεν εμποδίζουν την εκτέλεσή της
  • Η JavaScript είναι ταυτόχρονη, δηλαδή εκτελεί τον κώδικά της σε περισσότερα από ένα νήμα ταυτόχρονα
  • Η JavaScript είναι ασύγχρονη, δηλαδή εκτελεί κώδικα αποκλεισμού κάπου αλλού.

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

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

Κινητήρας V8

Η μηχανή V8 είναι μια μηχανή χρόνου εκτέλεσης συναρμολόγησης ιστού ανοικτού κώδικα υψηλής απόδοσης για JavaScript γραμμένη σε C++ από την Google. Τα περισσότερα προγράμματα περιήγησης εκτελούν JavaScript χρησιμοποιώντας τη μηχανή V8 και ακόμη και το δημοφιλές περιβάλλον χρόνου εκτέλεσης του κόμβου js το χρησιμοποιεί επίσης.

Σε απλά αγγλικά, το V8 είναι ένα πρόγραμμα C++, το οποίο λαμβάνει κώδικα JavaScript, τον μεταγλωττίζει και τον εκτελεί.

Το V8 κάνει δύο σημαντικά πράγματα.

  • Εκχώρηση μνήμης σωρού
  • Περιβάλλον εκτέλεσης στοίβας κλήσεων

Δυστυχώς, η υποψία μας ήταν λάθος. Το V8 έχει μόνο μία στοίβα κλήσεων, σκεφτείτε τη στοίβα κλήσεων ως το νήμα.

Ένα νήμα === μία στοίβα κλήσης === μία εκτέλεση κάθε φορά.

  Αξιόπιστη πλατφόρμα για μικρές και μεγάλες επιχειρήσεις

Εικόνα – Hacker Noon

Εφόσον το V8 έχει μόνο μία στοίβα κλήσεων, πώς τότε η JavaScript εκτελείται ταυτόχρονα και ασύγχρονα χωρίς να μπλοκάρει το κύριο νήμα εκτέλεσης;

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

Η JavaScript εκτελεί κάθε κώδικα γραμμή προς γραμμή, το ένα μετά το άλλο (με ένα νήμα). Όπως ήταν αναμενόμενο, η πρώτη γραμμή εκτυπώνεται στην κονσόλα εδώ, αλλά γιατί η τελευταία γραμμή εκτυπώνεται πριν από τον κωδικό χρονικού ορίου; Γιατί η διαδικασία εκτέλεσης δεν περιμένει τον κωδικό χρονικού ορίου (μπλοκαρίσματος) πριν προχωρήσει για να εκτελέσει την τελευταία γραμμή;

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

Ας ρίξουμε μια κλεφτή ματιά στο V8 Πηγαίος κώδικας για λίγο.

ΟΠΑ, τι??!!! Δεν υπάρχουν λειτουργίες χρονοδιακόπτη στο V8, δεν υπάρχουν DOM; Δεν υπάρχουν εκδηλώσεις; Όχι AJAX;…. Εεεεσσςς!!!

Τα συμβάντα, το DOM, τα χρονόμετρα κ.λπ. δεν αποτελούν μέρος της βασικής υλοποίησης της JavaScript, η JavaScript συμμορφώνεται αυστηρά με τις προδιαγραφές του Ecma Scripts και διάφορες εκδόσεις του αναφέρονται συχνά σύμφωνα με τις προδιαγραφές του Ecma Scripts (ES X).

Ροή εργασιών εκτέλεσης

Συμβάντα, χρονόμετρα, αιτήματα Ajax παρέχονται όλα στην πλευρά του πελάτη από τα προγράμματα περιήγησης και συχνά αναφέρονται ως Web API. Είναι αυτά που επιτρέπουν στη JavaScript με ένα νήμα να είναι μη αποκλειστική, ταυτόχρονη και ασύγχρονη! Αλλά πως?

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

Η στοίβα κλήσεων

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

Ας εξετάσουμε το παρακάτω παράδειγμα.

Πηγή – https://youtu.be/8aGhZQkoFbQ

Όταν καλείτε τη συνάρτηση printSquare() , αυτή προωθείται στη στοίβα κλήσεων, η συνάρτηση printSquare() καλεί τη συνάρτηση Square(). Η συνάρτηση Square() ωθείται στη στοίβα και καλεί επίσης τη συνάρτηση πολλαπλασιασμού(). Η συνάρτηση πολλαπλασιασμού ωθείται στη στοίβα. Εφόσον η συνάρτηση πολλαπλασιασμού επιστρέφει και είναι το τελευταίο πράγμα που ωθήθηκε στη στοίβα, επιλύεται πρώτα και αφαιρείται από τη στοίβα, ακολουθούμενη από τη συνάρτηση square() και μετά τη συνάρτηση printSquare().

  Ποιες είναι οι βαθμολογίες Valorant στη σειρά;

Το Web API

Εδώ εκτελείται ο κώδικας που δεν χειρίζεται ο κινητήρας V8 για να μην «μπλοκάρει» το κύριο νήμα εκτέλεσης. Όταν η Στοίβα κλήσεων συναντήσει μια συνάρτηση Web API, η διαδικασία παραδίδεται αμέσως στο Web API, όπου εκτελείται και ελευθερώνει τη Στοίβα κλήσεων να εκτελέσει άλλες λειτουργίες κατά την εκτέλεσή της.

Ας επιστρέψουμε στο παραπάνω παράδειγμα setTimeout.

Όταν εκτελούμε τον κώδικα, η πρώτη γραμμή console.log ωθείται στη στοίβα και παίρνουμε την έξοδο μας σχεδόν αμέσως, όταν φτάνουμε στο χρονικό όριο, οι χρονοδιακόπτες χειρίζονται από το πρόγραμμα περιήγησης και δεν αποτελούν μέρος της βασικής υλοποίησης του V8, ωθούνται στο Web API, ελευθερώνοντας τη στοίβα ώστε να μπορεί να εκτελέσει άλλες λειτουργίες.

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

Πως?

The Event Loop

Πριν συζητήσουμε τον βρόχο συμβάντος, ας περάσουμε πρώτα από τη συνάρτηση της ουράς εργασιών.

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

Η ουρά είναι μια δομή δεδομένων που λειτουργεί με βάση την αρχή First in First out, οπότε καθώς οι εργασίες ωθούνται στην ουρά, βγαίνουν με την ίδια σειρά. Οι εργασίες που έχουν εκτελεστεί από τα API Ιστού, οι οποίες προωθούνται στην ουρά εργασιών και, στη συνέχεια, επιστρέφουν στη Στοίβα κλήσεων για να εκτυπωθεί το αποτέλεσμά τους.

Αλλά περίμενε. ΤΙ ΚΑΛΟ ΕΙΝΑΙ Ο ΒΡΟΧΟΣ ΕΚΔΗΛΩΣΗΣ;;;

Πηγή – https://youtu.be/8aGhZQkoFbQ

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

Πηγή – https://www.quora.com/How-does-an-event-loop-work/answer/Timothy-Maxwell

Το παραπάνω διάγραμμα δείχνει τη βασική ροή εργασίας μεταξύ του βρόχου συμβάντων και της ουράς εργασιών.

συμπέρασμα

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

Η JavaScript είναι πάντα κατ’ απαίτηση και αν είστε περίεργοι να μάθετε, θα σας συμβούλευα να ελέγξετε αυτό Μάθημα Udemy.