Ελληνικά

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

JavaScript AbortController: Εξοικείωση με την Ακύρωση Ασύγχρονων Λειτουργιών

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

Κατανόηση της Ανάγκης για Ακύρωση

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

Εισαγωγή του AbortController και του AbortSignal

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

Βασική Χρήση: Ακύρωση Αιτημάτων Fetch

Ας ξεκινήσουμε με ένα απλό παράδειγμα ακύρωσης ενός αιτήματος fetch:


const controller = new AbortController();
const signal = controller.signal;

fetch('https://api.example.com/data', { signal })
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log('Data:', data);
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
    } else {
      console.error('Fetch error:', error);
    }
  });

// To cancel the fetch request:
controller.abort();

Επεξήγηση:

  1. Δημιουργούμε μια παρουσία AbortController.
  2. Λαμβάνουμε το σχετικό AbortSignal από τον controller.
  3. Μεταβιβάζουμε το signal στις επιλογές fetch.
  4. Εάν πρέπει να ακυρώσουμε το αίτημα, καλούμε την controller.abort().
  5. Στο μπλοκ .catch(), ελέγχουμε εάν το σφάλμα είναι AbortError. Εάν είναι, γνωρίζουμε ότι το αίτημα ακυρώθηκε.

Χειρισμός του AbortError

Όταν καλείται η controller.abort(), το αίτημα fetch θα απορριφθεί με ένα AbortError. Είναι ζωτικής σημασίας να χειριστείτε αυτό το σφάλμα κατάλληλα στον κώδικά σας. Η αποτυχία να το κάνετε αυτό μπορεί να οδηγήσει σε μη διαχειριζόμενες απορρίψεις promise και απροσδόκητη συμπεριφορά.

Ακολουθεί ένα πιο ισχυρό παράδειγμα με χειρισμό σφαλμάτων:


const controller = new AbortController();
const signal = controller.signal;

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data', { signal });
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    const data = await response.json();
    console.log('Data:', data);
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
      return null; // Or throw the error to be handled further up
    } else {
      console.error('Fetch error:', error);
      throw error; // Re-throw the error to be handled further up
    }
  }
}

fetchData();

// To cancel the fetch request:
controller.abort();

Βέλτιστες Πρακτικές για τον Χειρισμό του AbortError:

Ακύρωση Χρονοδιακοπτών με AbortSignal

Το AbortSignal μπορεί επίσης να χρησιμοποιηθεί για την ακύρωση χρονοδιακοπτών που δημιουργούνται με setTimeout ή setInterval. Αυτό απαιτεί λίγο περισσότερη χειροκίνητη εργασία, καθώς οι ενσωματωμένες λειτουργίες χρονοδιακόπτη δεν υποστηρίζουν άμεσα το AbortSignal. Πρέπει να δημιουργήσετε μια προσαρμοσμένη συνάρτηση που ακούει το σήμα ακύρωσης και καθαρίζει το χρονόμετρο όταν ενεργοποιείται.


function cancellableTimeout(callback, delay, signal) {
  let timeoutId;

  const timeoutPromise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(() => {
      resolve(callback());
    }, delay);

    signal.addEventListener('abort', () => {
      clearTimeout(timeoutId);
      reject(new Error('Timeout Aborted'));
    });
  });

  return timeoutPromise;
}

const controller = new AbortController();
const signal = controller.signal;


cancellableTimeout(() => {
  console.log('Timeout executed');
}, 2000, signal)
.then(() => console.log("Timeout finished successfully"))
.catch(err => console.log(err));

// To cancel the timeout:
controller.abort();

Επεξήγηση:

  1. Η συνάρτηση cancellableTimeout δέχεται μια συνάρτηση επανάκλησης, μια καθυστέρηση και ένα AbortSignal ως ορίσματα.
  2. Ρυθμίζει ένα setTimeout και αποθηκεύει το αναγνωριστικό χρονικού ορίου.
  3. Προσθέτει έναν ακροατή συμβάντων στο AbortSignal που ακούει το συμβάν abort.
  4. Όταν ενεργοποιείται το συμβάν abort, ο ακροατής συμβάντων καθαρίζει το χρονικό όριο και απορρίπτει την υπόσχεση.

Ακύρωση Ακροατών Συμβάντων

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


const controller = new AbortController();
const signal = controller.signal;

const button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log('Button clicked!');
}, { signal });

// To cancel the event listener:
controller.abort();

Επεξήγηση:

  1. Μεταβιβάζουμε το signal ως επιλογή στη μέθοδο addEventListener.
  2. Όταν καλείται η controller.abort(), ο ακροατής συμβάντων θα καταργηθεί αυτόματα.

AbortController σε Συστατικά React

Στο React, μπορείτε να χρησιμοποιήσετε το AbortController για να ακυρώσετε ασύγχρονες λειτουργίες όταν ένα στοιχείο αποσυνδέεται. Αυτό είναι απαραίτητο για την αποφυγή διαρροών μνήμης και σφαλμάτων που προκαλούνται από την ενημέρωση αποσυνδεδεμένων στοιχείων. Ακολουθεί ένα παράδειγμα χρησιμοποιώντας το hook useEffect:


import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data', { signal });
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        const data = await response.json();
        setData(data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          console.error('Fetch error:', error);
        }
      }
    }

    fetchData();

    return () => {
      controller.abort(); // Cancel the fetch request when the component unmounts
    };
  }, []); // Empty dependency array ensures this effect runs only once on mount

  return (
    
{data ? (

Data: {JSON.stringify(data)}

) : (

Loading...

)}
); } export default MyComponent;

Επεξήγηση:

  1. Δημιουργούμε ένα AbortController μέσα στο hook useEffect.
  2. Μεταβιβάζουμε το signal στο αίτημα fetch.
  3. Επιστρέφουμε μια συνάρτηση καθαρισμού από το hook useEffect. Αυτή η συνάρτηση θα κληθεί όταν το στοιχείο αποσυνδεθεί.
  4. Μέσα στη συνάρτηση καθαρισμού, καλούμε την controller.abort() για να ακυρώσουμε το αίτημα fetch.

Προηγμένες Περιπτώσεις Χρήσης

Αλυσιδωτή Διασύνδεση AbortSignals

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

Χρήση του AbortController με Βιβλιοθήκες Τρίτων

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

Οφέλη από τη Χρήση του AbortController

Συμβατότητα Προγράμματος Περιήγησης

Το AbortController υποστηρίζεται ευρέως στα σύγχρονα προγράμματα περιήγησης, συμπεριλαμβανομένων των Chrome, Firefox, Safari και Edge. Μπορείτε να ελέγξετε τον πίνακα συμβατότητας στα MDN Web Docs για τις πιο πρόσφατες πληροφορίες.

Polyfills

Για παλαιότερα προγράμματα περιήγησης που δεν υποστηρίζουν εγγενώς το AbortController, μπορείτε να χρησιμοποιήσετε ένα polyfill. Ένα polyfill είναι ένα κομμάτι κώδικα που παρέχει τη λειτουργικότητα μιας νεότερης δυνατότητας σε παλαιότερα προγράμματα περιήγησης. Υπάρχουν πολλά AbortController polyfills διαθέσιμα στο διαδίκτυο.

Συμπέρασμα

Η διεπαφή AbortController είναι ένα ισχυρό εργαλείο για τη διαχείριση ασύγχρονων λειτουργιών στην JavaScript. Χρησιμοποιώντας το AbortController, μπορείτε να γράψετε καθαρότερο, πιο αποδοτικό και πιο ισχυρό κώδικα που χειρίζεται την ακύρωση με χάρη. Είτε λαμβάνετε δεδομένα από API, ρυθμίζετε χρονοδιακόπτες είτε διαχειρίζεστε ακροατές συμβάντων, το AbortController μπορεί να σας βοηθήσει να βελτιώσετε τη συνολική ποιότητα των εφαρμογών web σας.

Περαιτέρω Ανάγνωση