Εισαγωγή στις Προϋποσχέσεις (Promises) στο JavaScript
Γνωρίζετε ήδη ότι η χρήση του μοντέλου ασυγχρονισμού με επανάκληση (callbacks) εύκολα οδηγεί σε μια κατάσταση που λέγεται callback hell. Για αυτό το λόγο, στο JavaScript εισήχθη ένα νέο μοντέλο που ονομάζεται προϋποσχέσεις (promise). Ας μελετήσουμε αυτό το μοντέλο.
Μια προϋπόσχεση αντιπροσωπεύει ένα αντικείμενο, στο οποίο ως παράμετρος μεταδίδεται μια συνάρτηση, μέσα στην οποία πρέπει να τοποθετούμε τον ασύγχρονο κώδικά μας:
let promise = new Promise(function() {
// ασύγχρονος κώδικας
});
Όπως βλέπετε, κατέγραψα το αντικείμενο με την προϋπόσχεση
σε μια μεταβλητή promise. Σε κάποιο άλλο
σημείο του κώδικα μπορώ να εφαρμόσω σε αυτή τη μεταβλητή
τη μέθοδο then, περνώντας σε αυτή μια συνάρτηση
με κώδικα, ο οποίος πρέπει να εκτελεστεί με την
ολοκλήρωση του ασύγχρονου κώδικα, που γράφτηκε
κατά τη δημιουργία αυτής της προϋπόσχεσης:
promise.then(function() {
// θα εκτελεστεί upon completion of the asynchronous code
});
Ακούγεται μπερδεμένο, γι' αυτό ας δούμε ένα παράδειγμα. Ας υποθέσουμε ότι έχω τον ακόλουθο ασύγχρονο κώδικα:
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
Ας πούμε ότι θέλω να λύσω γι' αυτόν το κύριο
πρόβλημα του ασυγχρονισμού: να εκτελέσω κάποιον
κώδικα αφού ενεργοποιηθεί το χρονόμετρο. Ταυτόχρονα
δεν θέλω να τοποθετήσω αυτόν τον κώδικα μέσα στο ίδιο το χρονόμετρο
και θέλω ο πιθανός αποτέλεσμα,
που έγραψα στη μεταβλητή result, να περάσει με κάποιο τρόπο σε αυτόν τον κώδικα.
Στην ουσία, λύναμε αυτό το πρόβλημα στα προηγούμενα
μαθήματα μέσω συναρτήσεων επανάκλησης και εγγραφών. Ας
δούμε τώρα πώς να το κάνουμε μέσω προϋποσχέσεων.
Αρχικά, πρέπει να τυλίξουμε τον ασύγχρονο κώδικα μας σε μια προϋπόσχεση:
let promise = new Promise(function() {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Αυτό, ωστόσο, δεν είναι αρκετό. Πρέπει να υποδείξουμε ρητά ότι ο ασύγχρονος κώδικάς μας ολοκληρώθηκε. Σε αυτό μας βοηθάει μια ειδική συνάρτηση ολοκλήρωσης, η οποία περνάει αυτόματα στην πρώτη παράμετρο της συνάρτησης, εάν αυτή έχει οριστεί:
let promise = new Promise(function(resolve) { // ορίζουμε την παράμετρο
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Με τη βοήθεια της συνάρτησης ολοκλήρωσης μπορούμε ρητά να υποδείξουμε στην προϋπόσχεση ότι ο ασύγχρονος κώδικας ολοκληρώθηκε. Για να το κάνουμε αυτό, πρέπει να καλέσουμε αυτή τη συνάρτηση στο επιθυμητό σημείο:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(); // ολοκληρώνουμε την προϋπόσχεση
}, 3000);
});
Ταυτόχρονα, εάν θέλουμε να μεταφέρουμε στο εξής κάποιο αποτέλεσμα του ασύγχρονου κώδικα, μπορούμε να το περάσουμε ως παράμετρο στη συνάρτηση ολοκλήρωσής μας:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(result); // μεταφέρουμε το αποτέλεσμα
}, 3000);
});
Μπορούμε, φυσικά, να απαλλαγούμε από την ενδιάμεση μεταβλητή:
let promise = new Promise(function(resolve) {
setTimeout(function() {
resolve([1, 2, 3, 4, 5]);
}, 3000);
});
Τώρα σε οποιοδήποτε άλλο σημείο μπορούμε να καλέσουμε
τη μέθοδο then της προϋπόσχεσής μας:
promise.then(function() {
// θα ενεργοποιηθεί upon completion της προϋπόσχεσης
});
Το αποτέλεσμα της προϋπόσχεσης θα περάσει στην πρώτη παράμετρο της συνάρτησης, εάν επιθυμούμε να την ορίσουμε:
promise.then(function(result) {
console.log(result); // θα εμφανίσει τον πίνακα με το αποτέλεσμα
});
Δημιουργήστε μια προϋπόσχεση, μέσα στην οποία θα υπάρχει μια καθυστέρηση
5 δευτερολέπτων, μετά από την οποία η προϋπόσχεση πρέπει
να ολοκληρωθεί, επιστρέφοντας ως αποτέλεσμά της κάποιο
κείμενο. Εμφανίστε αυτό το κείμενο στην οθόνη.