Το μοντέλο εκτέλεσης της JavaScript είναι πολύχρωμο και είναι εύκολο να παρεξηγηθεί. Η εκμάθηση για τον βρόχο συμβάντων στον πυρήνα του μπορεί να βοηθήσει.
Η JavaScript είναι μια γλώσσα με ένα νήμα, κατασκευασμένη για να χειρίζεται εργασίες μία κάθε φορά. Ωστόσο, ο βρόχος συμβάντων επιτρέπει στην JavaScript να χειρίζεται συμβάντα και επιστροφές κλήσεων ασύγχρονα, προσομοιώνοντας συστήματα ταυτόχρονου προγραμματισμού. Αυτό διασφαλίζει την απόδοση των εφαρμογών σας JavaScript.
Τι είναι ο βρόχος συμβάντων JavaScript;
Ο βρόχος συμβάντων της JavaScript είναι ένας μηχανισμός που εκτελείται στο παρασκήνιο κάθε εφαρμογής JavaScript. Επιτρέπει στην JavaScript να χειρίζεται εργασίες με τη σειρά χωρίς να μπλοκάρει το κύριο νήμα εκτέλεσής της. Αυτό αναφέρεται ως ασύγχρονος προγραμματισμός.
Ο βρόχος συμβάντος διατηρεί μια ουρά εργασιών προς εκτέλεση και τροφοδοτεί αυτές τις εργασίες προς τα δεξιά web API για εκτέλεση μία κάθε φορά. Η JavaScript παρακολουθεί αυτές τις εργασίες και χειρίζεται την καθεμία ανάλογα με το επίπεδο πολυπλοκότητας της εργασίας.
Για να κατανοήσετε την ανάγκη για τον βρόχο συμβάντων JavaScript και τον ασύγχρονο προγραμματισμό. Πρέπει να καταλάβετε ποιο πρόβλημα λύνει ουσιαστικά.
Πάρτε αυτόν τον κωδικό, για παράδειγμα:
functionlongRunningFunction() {
// This function does something that takes a long time to execute.
for (var i = 0; i < 100000; i++) {
console.log("Hello")
}
}functionshortRunningFunction(a) {
return a * 2 ;
}functionmain() {
var startTime = Date.now();
longRunningFunction();
var endTime = Date.now();// Prints the amount of time it took to execute functions
console.log(shortRunningFunction(2));
console.log("Time taken: " + (endTime - startTime) + " milliseconds");
}
main();
Αυτός ο κώδικας ορίζει πρώτα μια συνάρτηση που ονομάζεται longRunningFunction(). Αυτή η συνάρτηση θα κάνει κάποιου είδους πολύπλοκη χρονοβόρα εργασία. Σε αυτή την περίπτωση, εκτελεί α Για βρόχος που επαναλαμβάνεται πάνω από 100.000 φορές. Αυτό σημαίνει ότι console.log ("Γεια") τρέχει 100.000 φορές.
Ανάλογα με την ταχύτητα του υπολογιστή, αυτό μπορεί να διαρκέσει πολύ και να μπλοκάρει shortRunningFunction() από την άμεση εκτέλεση μέχρι να ολοκληρωθεί η προηγούμενη λειτουργία.
Για το περιβάλλον, ακολουθεί μια σύγκριση του χρόνου που απαιτείται για την εκτέλεση και των δύο συναρτήσεων:
Και μετά το single shortRunningFunction():
Η διαφορά μεταξύ μιας λειτουργίας 2.351 χιλιοστών του δευτερολέπτου και μιας λειτουργίας 0 χιλιοστών του δευτερολέπτου είναι προφανής όταν στοχεύετε να δημιουργήσετε μια εφαρμογή με απόδοση.
Πώς ο βρόχος συμβάντων βοηθά στην απόδοση της εφαρμογής
Ο βρόχος συμβάντος έχει διαφορετικά στάδια και μέρη που συμβάλλουν στη λειτουργία του συστήματος.
Η στοίβα κλήσεων
Η στοίβα κλήσεων JavaScript είναι απαραίτητη για τον τρόπο με τον οποίο η JavaScript χειρίζεται τις κλήσεις λειτουργιών και συμβάντων από την εφαρμογή σας. Ο κώδικας JavaScript μεταγλωττίζεται από πάνω προς τα κάτω. Ωστόσο, το Node.js, κατά την ανάγνωση του κώδικα, το Node.js θα εκχωρήσει κλήσεις λειτουργιών από κάτω προς τα πάνω. Καθώς διαβάζεται, ωθεί τις καθορισμένες λειτουργίες ως πλαίσια στη στοίβα κλήσεων μία προς μία.
Η στοίβα κλήσεων είναι υπεύθυνη για τη διατήρηση του πλαισίου εκτέλεσης και της σωστής σειράς των συναρτήσεων. Αυτό το κάνει λειτουργώντας ως στοίβα Last-In-First-Out (LIFO).
Αυτό σημαίνει ότι το τελευταίο πλαίσιο λειτουργιών που το πρόγραμμά σας ωθεί στη στοίβα κλήσεων θα είναι το πρώτο που θα βγει από τη στοίβα και θα εκτελεστεί. Αυτό θα διασφαλίσει ότι η JavaScript διατηρεί τη σωστή σειρά εκτέλεσης της συνάρτησης.
Η JavaScript θα βγάλει κάθε καρέ από τη στοίβα μέχρι να αδειάσει, που σημαίνει ότι όλες οι λειτουργίες έχουν ολοκληρωθεί.
Libuv Web API
Στον πυρήνα των ασύγχρονων προγραμμάτων της JavaScript βρίσκεται libuv. Η βιβλιοθήκη libuv είναι γραμμένη στη γλώσσα προγραμματισμού C, η οποία μπορεί να αλληλεπιδράσει με τη γλώσσα του λειτουργικού συστήματος χαμηλού επιπέδου API. Η βιβλιοθήκη θα παρέχει πολλά API που επιτρέπουν στον κώδικα JavaScript να εκτελείται παράλληλα με άλλα κώδικας. API για τη δημιουργία νημάτων, ένα API για την επικοινωνία μεταξύ νημάτων και ένα API για τη διαχείριση του συγχρονισμού νημάτων.
Για παράδειγμα, όταν χρησιμοποιείτε setTimeout στο Node.js για παύση της εκτέλεσης. Το χρονόμετρο ρυθμίζεται μέσω του libuv, το οποίο διαχειρίζεται τον βρόχο συμβάντος για να εκτελέσει τη λειτουργία επανάκλησης μόλις παρέλθει η καθορισμένη καθυστέρηση.
Ομοίως, όταν εκτελείτε λειτουργίες δικτύου ασύγχρονα, το libuv χειρίζεται αυτές τις λειτουργίες χωρίς αποκλεισμό τρόπο, διασφαλίζοντας ότι άλλες εργασίες μπορούν να συνεχίσουν την επεξεργασία χωρίς να περιμένουν τη λειτουργία εισόδου/εξόδου (I/O) τέλος.
Η ουρά επανάκλησης και συμβάντων
Η ουρά επανάκλησης και συμβάντων είναι εκεί όπου οι συναρτήσεις επανάκλησης περιμένουν για εκτέλεση. Όταν μια ασύγχρονη λειτουργία ολοκληρωθεί από το libuv, η αντίστοιχη συνάρτηση επανάκλησης προστίθεται σε αυτήν την ουρά.
Δείτε πώς πάει η σειρά:
- Η JavaScript μετακινεί ασύγχρονες εργασίες στο libuv για να τις χειρίζεται και συνεχίζει να χειρίζεται αμέσως την επόμενη εργασία.
- Όταν τελειώσει η ασύγχρονη εργασία, η JavaScript προσθέτει τη λειτουργία επανάκλησης στην ουρά επανάκλησης.
- Η JavaScript συνεχίζει να εκτελεί άλλες εργασίες στη στοίβα κλήσεων έως ότου ολοκληρωθούν όλα με την τρέχουσα σειρά.
- Μόλις αδειάσει η στοίβα κλήσεων, η JavaScript εξετάζει την ουρά επανάκλησης.
- Εάν υπάρχει επανάκληση στην ουρά, σπρώχνει την πρώτη στη στοίβα κλήσεων και την εκτελεί.
Με αυτόν τον τρόπο, οι ασύγχρονες εργασίες δεν αποκλείουν το κύριο νήμα και η ουρά επανάκλησης διασφαλίζει ότι οι αντίστοιχες επανακλήσεις εκτελούνται με τη σειρά που ολοκλήρωσαν.
Ο κύκλος βρόχου συμβάντων
Ο βρόχος συμβάντος έχει επίσης κάτι που ονομάζεται ουρά μικροεργασιών. Αυτή η ειδική ουρά στον βρόχο συμβάντων κρατά μικροεργασίες που έχουν προγραμματιστεί να εκτελεστούν μόλις ολοκληρωθεί η τρέχουσα εργασία στη στοίβα κλήσεων. Αυτή η εκτέλεση πραγματοποιείται πριν από την επόμενη επανάληψη βρόχου απόδοσης ή συμβάντος. Οι μικροεργασίες είναι εργασίες υψηλής προτεραιότητας με προτεραιότητα έναντι των κανονικών εργασιών στον βρόχο συμβάντων.
Μια μικροεργασία δημιουργείται συνήθως όταν εργάζεστε με το Promises. Κάθε φορά που μια Υπόσχεση επιλύεται ή απορρίπτεται, είναι η αντίστοιχη .έπειτα() ή .σύλληψη() Η επανάκληση εντάσσεται στην ουρά μικροεργασιών. Θα μπορούσατε να χρησιμοποιήσετε αυτήν την ουρά για να διαχειριστείτε εργασίες που χρειάζονται άμεση εκτέλεση μετά την τρέχουσα λειτουργία, όπως η ενημέρωση της διεπαφής χρήστη της εφαρμογής σας ή ο χειρισμός αλλαγών κατάστασης.
Για παράδειγμα, μια εφαρμογή Ιστού που εκτελεί ανάκτηση δεδομένων και ενημερώνει τη διεπαφή χρήστη με βάση τα δεδομένα που ανακτήθηκαν. Οι χρήστες μπορούν να ενεργοποιήσουν αυτήν την ανάκτηση δεδομένων κάνοντας επανειλημμένα κλικ σε ένα κουμπί. Κάθε κλικ κουμπιού ξεκινά μια λειτουργία ασύγχρονης ανάκτησης δεδομένων.
Χωρίς μικροεργασίες, ο βρόχος συμβάντων για αυτήν την εργασία θα λειτουργούσε ως εξής:
- Ο χρήστης κάνει επανειλημμένα κλικ στο κουμπί.
- Κάθε κλικ κουμπιού ενεργοποιεί μια λειτουργία ασύγχρονης ανάκτησης δεδομένων.
- Καθώς ολοκληρώνονται οι λειτουργίες ανάκτησης δεδομένων, η JavaScript προσθέτει τις αντίστοιχες επανακλήσεις στην κανονική ουρά εργασιών.
- Ο βρόχος συμβάντος ξεκινά την επεξεργασία εργασιών στην κανονική ουρά εργασιών.
- Η ενημέρωση διεπαφής χρήστη που βασίζεται στα αποτελέσματα ανάκτησης δεδομένων εκτελείται μόλις το επιτρέψουν οι κανονικές εργασίες.
Ωστόσο, με μικροεργασίες, ο βρόχος συμβάντων λειτουργεί διαφορετικά:
- Ο χρήστης κάνει επανειλημμένα κλικ στο κουμπί και ενεργοποιεί μια λειτουργία ασύγχρονης ανάκτησης δεδομένων.
- Καθώς ολοκληρώνονται οι λειτουργίες ανάκτησης δεδομένων, ο βρόχος συμβάντος προσθέτει τις αντίστοιχες επανακλήσεις στην ουρά μικροεργασιών.
- Ο βρόχος συμβάντος ξεκινά την επεξεργασία εργασιών στην ουρά μικροεργασιών αμέσως μετά την ολοκλήρωση της τρέχουσας εργασίας (κλικ στο κουμπί).
- Η ενημέρωση της διεπαφής χρήστη που βασίζεται στα αποτελέσματα της ανάκτησης δεδομένων εκτελείται πριν από την επόμενη κανονική εργασία, παρέχοντας μια πιο αποκριτική εμπειρία χρήστη.
Ακολουθεί ένα παράδειγμα κώδικα:
const fetchData = () => {
returnnewPromise(resolve => {
setTimeout(() => resolve('Data from fetch'), 2000);
});
};
document.getElementById('fetch-button').addEventListener('click', () => {
fetchData().then(data => {
// This UI update will run before the next rendering cycle
updateUI(data);
});
});
Σε αυτό το παράδειγμα, κάθε κλικ στο κουμπί "Λήψη" καλεί fetchData(). Κάθε λειτουργία ανάκτησης δεδομένων προγραμματίζεται ως μικροεργασία. Με βάση τα δεδομένα που ανακτήθηκαν, η ενημέρωση διεπαφής χρήστη εκτελείται αμέσως μετά την ολοκλήρωση κάθε λειτουργίας ανάκτησης, πριν από οποιεσδήποτε άλλες εργασίες βρόχου απόδοσης ή συμβάντων.
Αυτό διασφαλίζει ότι οι χρήστες βλέπουν τα ενημερωμένα δεδομένα χωρίς να αντιμετωπίζουν καθυστερήσεις λόγω άλλων εργασιών στον βρόχο συμβάντων.
Η χρήση μικροεργασιών σε σενάρια όπως αυτό μπορεί να αποτρέψει τα jank UI και να παρέχει ταχύτερες και ομαλότερες αλληλεπιδράσεις στην εφαρμογή σας.
Συνέπειες του βρόχου συμβάντων για την ανάπτυξη Ιστού
Η κατανόηση του βρόχου συμβάντων και του τρόπου χρήσης των δυνατοτήτων του είναι απαραίτητη για τη δημιουργία εφαρμογών με απόδοση και απόκριση. Ο βρόχος συμβάντων παρέχει ασύγχρονες και παράλληλες δυνατότητες, ώστε να μπορείτε να χειρίζεστε αποτελεσματικά πολύπλοκες εργασίες στην εφαρμογή σας χωρίς να διακυβεύεται η εμπειρία χρήστη.
Το Node.js παρέχει όλα όσα χρειάζεστε, συμπεριλαμβανομένων των εργαζομένων στον ιστό για την επίτευξη περαιτέρω παραλληλισμού εκτός του κύριου νήματος της JavaScript.