Πιθανότατα χρειάστηκε ο ιστότοπός σας να κάνει κάτι κάποια στιγμή, αλλά όχι αμέσως, μάλλον μετά από λίγα δευτερόλεπτα. Για να το πετύχει αυτό, η JavaScript προσφέρει ένα βασικό εργαλείο που ονομάζεται `setTimeout` , το οποίο ουσιαστικά λειτουργεί ως χρονόμετρο που, όταν φτάσει στο μηδέν, ενεργοποιεί μια συγκεκριμένη ενέργεια. Είναι μια από αυτές τις λειτουργίες που φαίνονται απλές με την πρώτη ματιά, αλλά έχουν τις ιδιορρυθμίες και τις τεχνικές λεπτομέρειες που αξίζει να γνωρίζετε για να αποφύγετε λάθη κατά τον προγραμματισμό.
Παρόλο που τη βλέπουμε συνεχώς στο πρόγραμμα περιήγησης, είναι σημαντικό να διευκρινίσουμε ότι αυτή η μέθοδος δεν αποτελεί μέρος της ίδιας της βασικής γλώσσας JavaScript, αλλά παρέχεται από το περιβάλλον εκτέλεσης . Αυτό σημαίνει ότι ενώ τη χρησιμοποιούμε στο Chrome ή τον Firefox, τη βρίσκουμε και στο Node.js, αν και με κάποιες διαφορές σε αυτά που επιστρέφει το σύστημα. Ας αναλύσουμε λεπτομερώς πώς λειτουργεί, από τα βασικά έως τα προηγμένα κόλπα για να κάνετε τις εφαρμογές σας να λειτουργούν ομαλά.
Τι ακριβώς είναι το setTimeout και πώς χρησιμοποιείται;

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

Όταν ρυθμίζουμε τον χρονοδιακόπτη, η δεύτερη παράμετρος είναι η καθυστέρηση . Αν δεν καθορίσουμε τίποτα, η προεπιλεγμένη τιμή είναι 0. Αλλά εδώ είναι το ενδιαφέρον κομμάτι: τι γίνεται αν η συνάρτησή μας χρειάζεται εξωτερικά δεδομένα; Υπάρχουν δύο βασικοί τρόποι για να το χειριστούμε αυτό. Ο πρώτος είναι μέσω μιας ανώνυμης συνάρτησης που αναδιπλώνει την αρχική κλήση, επιτρέποντάς μας να περάσουμε όποια ορίσματα θέλουμε. Ο δεύτερος, και πιο κομψός, τρόπος είναι να εκμεταλλευτούμε το γεγονός ότι η συνάρτηση `setTimeout` μας επιτρέπει να προσθέσουμε επιπλέον ορίσματα ξεκινώντας από την τρίτη παράμετρο, τα οποία αντιστοιχίζονται απευθείας στη συνάρτηση επανάκλησης.
Διαχείριση ακυρώσεων με clearTimeout

Μερικές φορές η ζωή παίρνει απροσδόκητες στροφές και πρέπει να ακυρώσουμε μια προγραμματισμένη εργασία που δεν έχει ακόμη εκτελεστεί. Για να το κάνουμε αυτό, πρέπει να γνωρίζουμε ότι η συνάρτηση `setTimeout` επιστρέφει ένα μοναδικό αναγνωριστικό (ένα `timerId`). Στα προγράμματα περιήγησης, αυτό το αναγνωριστικό είναι συνήθως ένας αριθμός, ενώ στο Node.js είναι ένα πιο σύνθετο αντικείμενο. Εάν αποθηκεύσουμε αυτήν την τιμή σε μια μεταβλητή, μπορούμε να καλέσουμε τη συνάρτηση ` clearTimeout(timerId)` για να ακυρώσουμε τη λειτουργία και να αποτρέψουμε την εκτέλεση του κώδικα, εξοικονομώντας έτσι πόρους συστήματος.
Σύγκριση: setTimeout vs setInterval

Είναι πολύ συνηθισμένο να συγχέονται αυτές οι δύο μέθοδοι. Ενώ η συνάρτηση `setTimeout` εκτελεί τη συνάρτηση μόνο μία φορά, η συνάρτηση `setInterval` την εκτελεί επανειλημμένα κάθε φορά που παρέρχεται το καθορισμένο χρονικό διάστημα. Ωστόσο, υπάρχει ένα προηγμένο κόλπο: η ένθετη συνάρτηση `setTimeout` . Αυτό περιλαμβάνει την κλήση μιας νέας συνάρτησης `setTimeout` ακριβώς στο τέλος της εκτέλεσης της τρέχουσας συνάρτησης.
Αυτή η τεχνική είναι πολύ πιο ευέλικτη από την `setInterval`, επειδή εγγυάται μια πραγματική και σταθερή καθυστέρηση μεταξύ του τέλους μιας εργασίας και της έναρξης της επόμενης. Με την `setInterval`, εάν η εκτέλεση της συνάρτησης διαρκεί περισσότερο από το χρονικό διάστημα, οι κλήσεις μπορούν να συσσωρευτούν ή να εκτελεστούν χωρίς παύση. Αντίθετα, η ένθεση σάς επιτρέπει να προσαρμόζετε δυναμικά τον χρόνο, κάτι που είναι ζωτικής σημασίας εάν, για παράδειγμα, υποβάλλετε αιτήματα σε έναν διακομιστή που ενδέχεται να είναι υπερφορτωμένος και χρειάζεται να αυξήσετε το διάστημα αναμονής.
Η περίεργη περίπτωση της μηδενικής καθυστέρησης και των περιορισμών
Αν χρησιμοποιήσετε την συνάρτηση `setTimeout(func, 0)` , μπορεί να νομίζετε ότι η συνάρτηση εκτελείται αμέσως, αλλά αυτό δεν ισχύει. Αυτό που συμβαίνει είναι ότι ο χρονοπρογραμματιστής τοποθετεί την εργασία σε ουρά για εκτέλεση το συντομότερο δυνατό , αλλά πάντα αφού ολοκληρωθεί πλήρως το τρέχον σενάριο. Είναι ένας τρόπος να πούμε, "Τελειώστε αυτό που κάνετε και το συντομότερο δυνατό, κάντε το".
Επιπλέον, είναι σημαντικό να σημειωθεί ότι τα προγράμματα περιήγησης επιβάλλουν ένα ελάχιστο όριο 4 ms για τους ένθετους χρονοδιακόπτες αφού έχουν εκτελεστεί πέντε συνεχόμενες φορές. Αυτό είναι ένα κατάλοιπο από παλαιότερες εκδόσεις για να αποτραπεί η διακοπή λειτουργίας του προγράμματος περιήγησης. Ωστόσο, η ακρίβεια δεν είναι ακριβής. Εάν η CPU είναι υπερφορτωμένη ή η καρτέλα εκτελείται στο παρασκήνιο , το πρόγραμμα περιήγησης ενδέχεται να καθυστερήσει την εκτέλεση έως και 300 ms ή ακόμα και ένα ολόκληρο δευτερόλεπτο για εξοικονόμηση ενέργειας μπαταρίας.
Υλοποίηση σε σύγχρονα πλαίσια
Αυτή η μέθοδος μεταφράζεται τέλεια σε εργαλεία όπως το React ή το Angular. Στο React , η ιδανική προσέγγιση είναι να τυλίξετε το `setTimeout` μέσα σε ένα άγκιστρο `useEffect` για να ελέγξετε τον κύκλο ζωής του στοιχείου και να διασφαλίσετε ότι ο χρονιστής εκκαθαρίζεται με τη συνάρτηση return, αποτρέποντας έτσι τις διαρροές μνήμης. Στο Angular , μπορεί εύκολα να ενσωματωθεί στον κατασκευαστή του στοιχείου ή στα άγκιστρα κύκλου ζωής για να ενεργοποιήσει ειδοποιήσεις ή να φορτώσει ασύγχρονα δεδομένα.
Για όσους αναζητούν μεγαλύτερα επίπεδα πολυπλοκότητας, οι χρονοδιακόπτες μπορούν να συνδυαστούν με Promises και async/await . Αυτό επιτρέπει τη δημιουργία πολύ πιο ευανάγνωστων και επαγγελματικών ακολουθιών αναμονής, αποφεύγοντας την περίφημη "κόλαση της επανάκλησης" και επιτρέποντας την ασύγχρονη και με τάξη διαχείριση πολλαπλών χρονοδιακόπτων.
Η δυνατότητα διαχείρισης χρόνου σε JavaScript είναι θεμελιώδης για τη δημιουργία δυναμικών διεπαφών, από ψηφιακά ρολόγια και κινούμενα σχέδια έως συστήματα επανάληψης σύνδεσης. Η εξοικείωση με το `setTimeout`, η παράκαμψή του με το `clearTimeout` και η κατανόηση του τρόπου με τον οποίο αλληλεπιδρά με τον βρόχο συμβάντων σάς επιτρέπει να βελτιστοποιήσετε την απόδοση της εφαρμογής και να βελτιώσετε την εμπειρία του τελικού χρήστη, έχοντας πάντα κατά νου ότι η ακρίβεια του χρόνου εξαρτάται σε μεγάλο βαθμό από το περιβάλλον και το φόρτο του συστήματος.