Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ab9e91e
asyn/await
LazarosZiskos May 8, 2025
98d9c2d
working on promises
LazarosZiskos May 15, 2025
10d3367
finished promises
LazarosZiskos May 15, 2025
019d8b7
Αλλαγή γένους promise
LazarosZiskos May 17, 2025
687d6f9
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
d0b4cfe
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
a196139
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
c9daad2
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
7f37b4d
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
9d93eff
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
8fd8004
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
ba8bf8a
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
b58872e
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
b1b18c2
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
0f52476
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
3a6ef40
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
fc6a371
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
bcbbb8d
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
765831f
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
93742b1
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
47d81a2
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
708b834
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
2ca67ed
Update docs-language/asynchronous/3. promises.md
LazarosZiskos Jul 16, 2025
82a56db
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
7949239
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
2b1420f
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
64c2a9f
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
84929da
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
a461446
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
a34c125
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
f59f378
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
00db404
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
1693b37
Update docs-language/asynchronous/4. async-await.md
LazarosZiskos Jul 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions docs-language/asynchronous/3. promises.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Promises

Όταν γράφουμε ασύγχρονο κώδικα στη JavaScript, μία μοντέρνα μεθόδος για να χειριστούμε αποτελέσματα που θα λάβουμε μελλοντικά (όπως απαντήσεις από έναν server), είναι μέσω της χρήσης των Promises. Τα Promises μας επιτρέπουν να οργανώνουμε αλυσιδωτές λειτουργίες και να διαχειριζόμαστε επιτυχίες και αποτυχίες σε ασύγχρονες διαδικασίες, αποφεύγοντας το γνωστό "Callback Hell" που αναφέραμε στην προηγούμενη ενότητα.

## Δημιουργία ενός Promise

Ένα Promise δημιουργείται μέσω του constructor `promise`, ο οποίος δέχεται μια συνάρτηση με δύο παραμέτρους. Η συνάρτηση αυτή ονομάζεται executor (εκτελεστής) και εκτελείται αυτόματα μόλις δημιουργηθεί το Promise.

Τα δύο ορίσματα που δέχεται, `resolve` και `reject`, είναι callback functions και έχουν τις εξής λειτουργίες:

- resolve: Η διαδικασία επιτυγχάνει και μας επιστρέφεται η τελική τιμή.
- reject: Η διαδικασία αποτυγχάνει και μας επιστρέφεραι ένα error `object`, δηλαδή το exception value.

```javascript
const myPromise = new Promise((resolve, reject) => {
const success = true;

if (success) {
resolve("Επιτυχία!");
} else {
reject("Αποτυχία");
}
});
```
Στο παραπάνω παράδειγμα, η `arrow function` είναι η συνάρτηση executor. Η παράμετρος `resolve` καλείται καθώς η διαδικασία που θέλουμε να εκτελέσουμε στην executor function επιτυγχάνει.

## Κατάσταση ενός Promise

Ένα Promise έχει τρείς δυνατές καταστάσεις:

| Κατάσταση | Περιγραφή |
|-----------|--------------------------------------------|
| `pending` | Το promise δεν έχει ακόμη επιλυθεί |
| `fulfilled` | Το promise επιλύθηκε με επιτυχία |
| `rejected` | Το promise απορρίφθηκε λόγω σφάλματος |

Μόλις φύγει από την κατάσταση `Pending`, το Promise "κλειδώνει και δεν αλλάζει ξανά κατάσταση.

## Μέθοδοι then και catch

Για να χειριστούμε το αποτέλεσμα ενός Promise, χρησιμοποιούμε τις μεθόδους `.then()` και `.catch()`.

- H `then` καλείται όταν το Promise επιλυθεί επιτυχώς.
- Η `catch` καλείται όταν το Promise απορριφθεί λόγω σφάλματος.

```javascript
let promise = new Promise((resolve, reject) => {
resolve("success");
});

myPromise
Comment thread
LazarosZiskos marked this conversation as resolved.
.then((message) => {
console.log("Μήνυμα": message);
})
.catch((error) => {
console.error("Σφάλμα": error);
});
```
- H `then` καλείται όταν το Promise επιλυθεί επιτυχώς.
- Η `catch` καλείται όταν το Promise απορριφθεί λόγω σφάλματος.

:::tip

Αν καλέσεις `.then()` ή `.catch()` πάνω σε ένα Promise που έχει *ήδη* επιλυθεί ή απορριφθεί, ο χειριστής θα εκτελεστεί άμεσα, χωρίς καθυστέρηση. Τα Promises είναι *μιας χρήσης* που σημαίνει ότι δεν μπορούν να "επαναληφθούν" ή να "ξαναπροσπαθήσουν".

:::


## Αλυσιδωτές Λειτουργίες (Chaining)

Ένα από τα χαρακτηριστικά των **Promises** είναι η δυνατότητα να δημιουργόυμε αλυσίδες ενεργειων. Για παράδειγμα:

```javascript
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())
.then((data) => {
console.log("Δεδομένα:", data)
});
.catch((error) => {
cosole.error("Σφάλμα στο fetch:", error);
});
```
Κάθε `then` επιστρέφει ένα νέο Promise, επιτρέποντας συνεχή επεξεργασία δεδομένων.

## Παραδείγματα

* Promise με καθυστέρηση

```javascript
function delay(ms) {
return new Promise((resolve) => {
setTimeout(() => resolve(`Έγινε μετά από ${ms}ms`), ms);
});
}

delay(1000).then((msg) => console.log(msg));
```

* Χειρισμός Σφαλμάτων

```javascript
function riskyOperation() {
return new Promise((resolve, reject) => {
const ok = Math.random() > 0.5;
ok ? resolve("Όλα καλά") : reject("Κάτι πήγε στραβά");
});
}

riskyOperation()
.then(console.log)
.catch(console.error);
```

## Promise.all και Promise.race

Η Javascript παρέχει μερικές βοηθητικές στατικές μεθόδους για συνδιασμό πολλών **Promises**:

* `Promise.all`
Εκτελεί πολλά Promises και περιμένει να ολοκληρωθούν όλες. Παράδειγμα:

```javascript
Promise.all([
fetch("/data1.json"),
fetch("/data2.json")
])
.then(([res1, res2]) => Promise.all([res1.json(), res2.json()]))
.then(([data1, data2]) => {
console.log("Δεδομένα 1:", data1);
console.log("Δεδομένα 2:", data2);
})
.catch(console.error);
```
Αν ένα αποτύχει, απορρίπτεται ολόκληρο το **Promise**.

* `Promise.race`
Επιστρέφει το αποτέλεσμα του πρώτου **Promise** που θα ολοκληρωθεί.
```javascript
const fast = new Promise(res => setTimeout(() => res("Γρήγορη"), 500));
const slow = new Promise(res => setTimeout(() => res("Αργή"), 1000));

Promise.race([fast, slow]).then(console.log); // "Γρήγορη"
```

# Πλεονεκτήματα Promises

- Καθαρός κώδικας απο τα callbacks.
- Αποφυγή nested callbacks (callback hell).
- Εύκολος χειρισμός σφαλμάτων με `.catch()`.
- Συμβατότητα με `async/await`, για καθαρότερο κώδικα.

# Σύγκριση με άλλες μεθόδους

| Μέθοδος | Πλεονεκτήματα | Μειονεκτήματα |
|---------------|--------------------------------------------|------------------------------------------------|
| Callbacks | Απλή και ευέλικτη | Δύσκολος έλεγχος ροής, callback hell |
| Promises | Καλύτερη ροή, ευκολότερο debugging | Περίπλοκες αλυσίδες μπορεί να μπερδέψουν |
| Async/Await | Συγχρονική μορφή, πιο καθαρός χειρισμός | Απαιτεί κατανόηση των Promises |


# Συμπέρασμα

Τα Promises είναι βασικά εργαλεία για τη συγγραφή ασύγχρονου κώδικα στη Javascript. Διευκολύνουν τον έλεγχο ροής, τον χειρσμό σφαλμάτων και συνεργάζονται άψογα με το `async/await`. Κατανοώντας τα Promises, αποκτάς τον έλεγχο των ασύγχρονων λειτουργιών της Javascript με καθαρό, επεκτάσιμο τροπο.

160 changes: 160 additions & 0 deletions docs-language/asynchronous/4. async-await.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Async/Await

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

Η λέξη κλειδί `async` χρησιμοποιείται μπροστά από μία συνάρτηση ή μέθοδο, καθιστώντας την ασύγχρονη. Όταν καλείται, επιστρέφει άμεσα ένα promise, το οποίο εκπληρώνεται μόλις η συνάρτηση επιστρέψει μια τιμή ή απορρίπτεται αν προκύψει εξαίρεση κατά την εκτέλεση.

Μέσα σε μια τέτοια συνάρτηση, μπορεί να χρησιμοποιηθεί η λέξη κλειδί 'await' για να «παγώσει» προσωρινά την εκτέλεση της μέχρι να ολοκληρωθεί το αντίστοιχο promise. Αν αυτό αποτύχει, ένα exception θα συμβεί στο σημείο του await, επιτρέποντας έτσι τη διαχείριση σφαλμάτων.

Ας δούμε κάποια παραδείγματα:

```javascript
async function fetchData() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
console.log(data);
}
fetchData();

// { "userId": 1,
// "id": 1,
// "title": "....",
// "body:" "..." }
```

Σε αυτό το παράδειγμα, η ασύγχρονη συνάρτηση `fetchData` περιμένει το αποτέλεσμα της εντολής 'fetch' και το μετατρέπει σε JSON πριν το εκτυπώσει.

```javascript
async function myFunction() {
try {
const result = await someAsyncFunction();
consolge.log(result);
}
catch (error) {
console.error("Σφάλμα", error.message);
}
}
```

Το παραπάνω παράδειγμα δείχνει τη χρήση της ασύγχρονης σύνταξης async/await σε συνδυασμό με τη δομή try/catch για διαχείριση σφαλμάτων. Η myFunction είναι μια ασύγχρονη συνάρτηση που περιμένει το αποτέλεσμα της someAsyncFunction() χρησιμοποιώντας το await. Αν το Promise επιλυθεί επιτυχώς, το αποτέλεσμα αναγράφεται στην κονσόλα. Αν προκύψει σφάλμα κατά την εκτέλεση της ασύγχρονης λειτουργίας, το exception εντοπίζεται στο catch και εμφανίζεται αντίστοιχο μήνυμα σφάλματος. Αυτή η προσέγγιση κάνει τη ροή του κώδικα πιο καθαρή και ευανάγνωστη, σε σύγκριση με τη χρήση 'then()' και 'catch()'.

## Χειρισμός Σφαλμάτων με try/catch

Ο χειρισμός σφαλμάτων σε `async` συναρτήσεις γίνεται μεσω της χρήσης της δομής `try/catch`, όπως είδαμε στο προηγούμενο παράδειγμα. Αυτό μας δίνει τον έλεγχο σε κάθε πιθανό σφάλμα που μπορεί να προκύψει κατά την αναμονή ενός Promise.

```javascript
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Σφάλμα κατά τη λήψη δεδομένων:", error);
}
}
```

H `try` "περιμένει" το αποτέλεσμα της `fetch` και η `catch` πιάνει οποιοδήποτε σφάλμα, είτε από το δίκτυο είτε κατά την επεξεργασία των δεδομένων.

## Συχνές Χρήσεις

Η σύνταξη async/await χρησιμοποιείται κυρίως σε:

- Αιτήματα σε APIs
```javascript
sync function fetchUser() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const user = await response.json();
console.log('Χρήστης:', user.name);
} catch (error) {
console.error('Σφάλμα στο fetch:', error.message);
}
}

fetchUser();
```
Χρησιμοποιούμε το λεκτικό `await` για να περιμένουμε την απάντηση ενός API και στη συνέχεια να μετατρέψουμε τα δεδομένα σε JSON.

- Ανάγνωση αρχείων σε Node.js
```javascript
const fs = require('fs/promise');

async function readFileContent() {
try {
const content = await fs.readFile('example.txt', 'utf8');
console.log('Περιεχόμενο:', content);
} catch(error) {
console.error("Σφάλμα ανάγνωσης αρχείου:", error);
}
}
readFileContent();
```
Διαβάζουμε ένα αρχείο τοπικά μέσω `fs.promises.readFile`, χωρίς `.then()` ή εμφώλευση.

- Διαδοχικές ασύγχρονες λειτουργίες με εξαρτήσεις
```javascript
async function loadUserData() {
try {
const user = await fetchUser(); // Βήμα 1
const posts = await fetchPosts(user.id); // Βήμα 2
const comments = await fetchComments(posts[0].id); // Βήμα 3

console.log("Σχόλια στην πρώτη ανάρτηση:", comments);
} catch (error) {
console.error("Σφάλμα κατά τη φόρτωση δεδομένων:", error.message)
}
}

// Dummy async functions
async function fetchUser() {
return { id: 1, name: 'Νίκος' };
}
async function fetchPosts(userId) {
return [{ id: 101, title: 'Πρώτη Ανάρτηση' }];
}
async function fetchComments(postId) {
return ['Πολύ καλό άρθρο!', 'Ενδιαφέρον.'];
}

loadUserData();
```
Το παραπάνω παράδειγμα δείχνει πώς μπορούμε να εκτελέσουμε διαδοχικές ασύγχρονες λειτουργίες χρησιμοποιώντας τη σύνταξη async/await. Αρχικά γίνεται ανάκτηση ενός χρήστη, στη συνέχεια φορτώνονται οι αναρτήσεις του και τέλος τα σχόλια της πρώτης ανάρτησης. Όλα αυτά περικλείονται σε δομή try/catch, ώστε να εντοπίζονται και να διαχειρίζονται τυχόν σφάλματα κατά τη διάρκεια της διαδικασίας. Κάθε βήμα εξαρτάται από το προηγούμενο και χωρίς την σύνταξη async/await αυτό θα γινόταν πολύπλοκο με εμφωλευμένα `.then()`.

- Αποφυγή `.then()` chaining και εμφωλευμένων callbacks
```javascript
async function loadProfile() {
try {
const user = await getUser();
const settings = await getSettings(user.id);
console.log('Ρυθμίσεις για:', user.name, settings);
} catch (error) {
console.error('Σφάλμα:', error.message);
}
}

// Mock async functions
const getUser = async () => ({ id: 42, name: 'Μαρία' });
const getSettings = async (userId) => ({ theme: 'dark', language: 'el' });

loadProfile();
```
Αντί για `getUser().then().then()...,` χρησιμοποιούμε await για να γράψουμε τον κώδικα σε "γραμμική" μορφή.

## Πλεονεκτήματα της async/await
- Βελτιωμένη Αναγνωσιμότητα: Ο κώδικας είναι πιο ευανάγνωστος και μοιάζει συγχρονικός.
- Εύκολος Χειρισμός Σφαλμάτων: Η χρήση `try/catch` κάνει τον χειρισμό σφαλμάτων πολύ πιο απλό.
- Αποφυγή Callback Hell: Δεν χρειάζονται εμφωλευμένα callbacks ούτε μακροσκελείς αλυσίδες `.then()`.
- Καλύτερο Debugging: Ο εντοπισμός σφαλμάτων είναι πιο απλός, καθώς η ροή θυμίζει συγχρονικό κώδικα.

## 5. Σύγκριση με άλλες προσεγγίσεις

| Προσέγγιση | Πλεονεκτήματα | Μειονεκτήματα |
|----------------|--------------------------------------------------------|----------------------------------------------------------|
| **Callbacks** | Απλή υλοποίηση, παλιότερη υποστήριξη | Callback hell, δύσκολος έλεγχος σφαλμάτων |
| **Promises** | Αλυσιδωτές λειτουργίες, καλύτερη από τα callbacks | Ακόμη δύσκολος χειρισμός σε πολύπλοκες ροές |
| **Async/Await**| Καθαρός και ευθύγραμμος κώδικας, χρήση try/catch | Απαιτεί κατανόηση των Promises και ES2017+ περιβάλλον |