Detaillierte Erklärung der neuen Funktionen von ES9: Asynchrone Iteration

Detaillierte Erklärung der neuen Funktionen von ES9: Asynchrone Iteration

Asynchrones Durchlaufen

Bevor wir die asynchrone Durchquerung erklären, erinnern wir uns noch einmal an die synchrone Durchquerung in ES6.

Gemäß der Definition von ES6 besteht die Iteration im Wesentlichen aus drei Teilen:

Iterierbar

Schauen wir uns zunächst die Definition von Iterable an:

Schnittstelle Iterable {
    [Symbol.iterator]() : Iterator;
}

Iterierbar bedeutet, dass dieses Objekt durchsuchbare Daten enthält und eine Factory-Methode implementieren muss, die einen Iterator generieren kann.

Iterator

Schnittstelle Iterator {
    nächstes() : IteratorErgebnis;
}

Iteratoren können aus Iterables konstruiert werden. Der Iterator ist ein Cursor-ähnliches Konzept, und auf das IteratorResult kann über „next“ zugegriffen werden.

IteratorErgebnis

IteratorResult sind die Daten, die bei jedem Aufruf der nächsten Methode erhalten werden.

Schnittstelle IteratorResult {
    Wert: beliebig;
    fertig: Boolesch;
}

Neben einem Wert, der die abzurufenden Daten darstellt, verfügt IteratorResult auch über ein Done, das angibt, ob die Durchquerung abgeschlossen ist.

Hier ist ein Beispiel für die Iteration über ein Array:

> const iterierbar = ['a', 'b'];

> const iterator = iterierbar[Symbol.iterator]();

iterator.weiter()

{ Wert: 'a', fertig: false }

iterator.weiter()

{ Wert: 'b', fertig: false }

iterator.weiter()

{ Wert: undefiniert, fertig: true }

Das obige Beispiel durchläuft jedoch synchrone Daten. Wenn wir asynchrone Daten erhalten, z. B. vom http-Ende heruntergeladene Dateien, möchten wir die Datei zeilenweise durchlaufen. Da das Lesen einer Datenzeile ein asynchroner Vorgang ist, werden hierbei asynchrone Daten durchlaufen.

Fügen Sie die asynchrone Dateilesemethode readLinesFromFile hinzu, dann ist die synchrone Durchlaufmethode nicht mehr auf die asynchrone anwendbar:

//Nicht mehr anwendbar für (const line of readLinesFromFile(fileName)) {
    console.log(Zeile);
}

Sie fragen sich vielleicht, ob wir den Vorgang des asynchronen Lesens einer Zeile in einem Promise kapseln und es dann synchron durchlaufen können?

Die Idee ist gut, aber in diesem Fall ist es unmöglich festzustellen, ob der asynchrone Vorgang abgeschlossen wurde. Daher ist diese Methode nicht durchführbar.

Daher führte ES9 das Konzept der asynchronen Durchquerung ein:

1. Sie können Symbol.asyncIterator verwenden, um den Iterator in asynchronen Iterables zu erhalten.

2. Die next()-Methode des asynchronen Iterators gibt ein Promises-Objekt zurück, das IteratorResults enthält.

Schauen wir uns also die API-Definition der asynchronen Durchquerung an:

Schnittstelle AsyncIterable {
    [Symbol.asyncIterator]() : AsyncIterator;
}
Schnittstelle AsyncIterator {
    nächstes() : Versprechen<IteratorResult>;
}
Schnittstelle IteratorResult {
    Wert: beliebig;
    fertig: Boolesch;
}

Schauen wir uns eine asynchrone Durchquerungsanwendung an:

asyncIterable = createAsyncIterable(['a', 'b']);
const asyncIterator = asyncIterable[Symbol.asyncIterator]();
asyncIterator.next()
.then(iterResult1 => {
    console.log(iterResult1); // { Wert: 'a', fertig: false }
    gibt asyncIterator.next() zurück;
})
.then(iterResult2 => {
    console.log(iterResult2); // { Wert: 'b', fertig: false }
    gibt asyncIterator.next() zurück;
})
.then(iterResult3 => {
    console.log(iterResult3); // { Wert: undefiniert, fertig: true }
});

Unter anderem konvertiert createAsyncIterable ein synchrones Iterable in ein asynchrones Iterable. Im nächsten Abschnitt erfahren Sie, wie es generiert wird.

Hier konzentrieren wir uns hauptsächlich auf den Durchlaufvorgang von asyncIterator.

Da ES8 den Async-Operator einführt, können wir den obigen Code auch mit der Async-Funktion umschreiben:

asynchrone Funktion f() {
    asyncIterable = createAsyncIterable(['a', 'b']);
    const asyncIterator = asyncIterable[Symbol.asyncIterator]();
    console.log(warte auf asyncIterator.next());
        // { Wert: 'a', fertig: false }
    console.log(warte auf asyncIterator.next());
        // { Wert: 'b', fertig: false }
    console.log(warte auf asyncIterator.next());
        // { Wert: undefiniert, fertig: true }
}

Asynchrone iterierbare Durchquerung

Verwenden Sie for-of, um ein synchrones Iterable zu durchlaufen, und verwenden Sie for-await-of, um ein asynchrones Iterable zu durchlaufen.

asynchrone Funktion f() {
    für warten (const x von createAsyncIterable(['a', 'b'])) {
        console.log(x);
    }
}
// Ausgabe:
// A
// B

Beachten Sie, dass „await“ in einer asynchronen Funktion platziert werden muss.

Wenn bei unserer asynchronen Durchquerung eine Ausnahme auftritt, können wir try catch in for-await-of verwenden, um die Ausnahme abzufangen:

Funktion createRejectingIterable() {
    zurückkehren {
        [Symbol.asyncIterator]() {
            gib dies zurück;
        },
        nächste() {
            return Promise.reject(neuer Fehler('Problem!'));
        },
    };
}
(asynchrone Funktion () { 
    versuchen {
        für warten (const x von createRejectingIterable()) {
            console.log(x);
        }
    } fangen (e) {
        konsole.fehler(e);
            // Fehler: Problem!
    }
})();

Das synchrone Iterable gibt synchrone Iteratoren zurück und die nächste Methode gibt {value, done} zurück.

Wenn Sie for-await-of verwenden, werden synchrone Iteratoren in asynchrone Iteratoren umgewandelt. Der zurückgegebene Wert wird dann in ein Promise umgewandelt.

Wenn der vom synchronen nächsten zurückgegebene Wert selbst ein Promise-Objekt ist, ist der asynchrone Rückgabewert immer noch dasselbe Promise.

Das heißt, es wird Folgendes konvertiert: Iterable<Promise<T>> in AsyncIterable<T>, wie im folgenden Beispiel gezeigt:

asynchrone Funktion main() {
    const syncIterable = [
        Versprechen.lösen('a'),
        Versprechen.resolve('b'),
    ];
    für warten (const x von syncIterable) {
        console.log(x);
    }
}
hauptsächlich();

// Ausgabe:
// A
// B

Das obige Beispiel wandelt ein synchrones Promise in ein asynchrones Promise um.

asynchrone Funktion main() {
    für warte (const x von ['a', 'b']) {
        console.log(x);
    }
}
hauptsächlich();

// Ausgabe:
// C
// D

Das obige Beispiel konvertiert eine synchrone Konstante in ein Promise. Sie können sehen, dass die Ergebnisse dieselben sind.

Asynchrone iterierbare Generierung

Zurück zum obigen Beispiel: Wir verwenden createAsyncIterable(syncIterable), um syncIterable in AsyncIterable zu konvertieren.

Sehen wir uns an, wie diese Methode implementiert wird:

asynchrone Funktion* erstelleAsyncIterable(syncIterable) {
    für (const elem von syncIterable) {
        Ertragselement;
    }
}

Im obigen Code fügen wir vor einer normalen Generatorfunktion „async“ hinzu, was bedeutet, dass es sich um einen asynchronen Generator handelt.

Bei gewöhnlichen Generatoren wird bei jedem Aufruf der nächsten Methode ein Objekt {value, done} zurückgegeben. Dieses Objekt ist eine Kapselung des Ertragswerts.

Bei einem asynchronen Generator wird bei jedem Aufruf der nächsten Methode ein Promise-Objekt zurückgegeben, das das Objekt {value, done} enthält. Dieses Objekt ist eine Kapselung des Ertragswerts.

Da ein Promise-Objekt zurückgegeben wird, müssen wir nicht warten, bis das Ergebnis der asynchronen Ausführung abgeschlossen ist, bevor wir die nächste Methode erneut aufrufen.

Wir können ein Promise.all verwenden, um alle asynchronen Promise-Operationen gleichzeitig auszuführen:

const asyncGenObj = createAsyncIterable(['a', 'b']);
const [{Wert:v1},{Wert:v2}] = warte auf Promise.all([
    asyncGenObj.next(), asyncGenObj.next()
]);
console.log(v1, v2); // ab

In createAsyncIterable erstellen wir ein asynchrones Iterable aus einem synchronen Iterable.

Als nächstes schauen wir uns an, wie man aus einem asynchronen Iterable ein asynchrones Iterable erstellt.

Aus dem vorherigen Abschnitt wissen wir, dass wir for-await-of verwenden können, um Daten aus einem asynchronen Iterable zu lesen. Daher können wir es folgendermaßen verwenden:

asynchrone Funktion * Präfixzeilen (asyncIterable) {
    für warten (const Zeile von asyncIterable) {
        Ertrag '' > ' + Zeile;
    }
}

Im Generator-Artikel haben wir über das Aufrufen von Generatoren innerhalb von Generatoren gesprochen. Das heißt, in einem Produzenten wird ein anderer Generator mithilfe von yield* aufgerufen.

Ebenso können wir dasselbe in einem Asynchrongenerator tun:

asynchrone Funktion* gen1() {
    Ertrag 'a';
    Ertrag 'b';
    Rückgabe 2;
}
asynchrone Funktion* gen2() {
    const Ergebnis = Ertrag*gen1(); 
        // Ergebnis === 2
}

(asynchrone Funktion () {
    für warte (const x von gen2()) {
        console.log(x);
    }
})();
// Ausgabe:
// A
// B

Wenn in einem asynchronen Generator eine Ausnahme ausgelöst wird, wird die Ausnahme auch in ein Promise verpackt:

asynchrone Funktion* asyncGenerator() {
    neuen Fehler werfen('Problem!');
}
asyncGenerator().weiter()
.catch(err => console.log(err)); // Fehler: Problem!

Asynchrone Methoden und asynchrone Generatoren

Eine asynchrone Methode ist eine mit einer asynchronen Funktion deklarierte Methode, die ein Promise-Objekt zurückgibt.

Die Rückgabe oder die ausgelöste Ausnahme in der Funktion wird als Wert im zurückgegebenen Promise verwendet.

(asynchrone Funktion () {
    gib "Hallo" zurück;
})()
.then(x => console.log(x)); // hallo

(asynchrone Funktion () {
    neuen Fehler werfen('Problem!');
})()
.catch(x => console.error(x)); // Fehler: Problem!

Asynchrone Generatoren sind Methoden, die mit der asynchronen Funktion * deklariert werden. Es gibt ein asynchrones Iterable zurück.

Durch den Aufruf der nächsten Methode von Iterable wird ein Promise zurückgegeben. Der vom asynchronen Generator gelieferte Wert wird verwendet, um den Wert des Promise auszufüllen. Wenn im Generator eine Ausnahme ausgelöst wird, wird sie auch von Promise abgefangen.

asynchrone Funktion* gen() {
    ergebe "Hallo";
}
const genObj = gen();
genObj.next().then(x => console.log(x));
    // { Wert: 'Hallo', fertig: false }

Oben finden Sie eine ausführliche Erläuterung der neuen Funktion von ES9, der asynchronen Iteration. Weitere Informationen zur neuen Funktion von ES9, der asynchronen Iteration, finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • ES6 Iterator-Traversal-Prinzip, Anwendungsszenarien und zugehörige allgemeine Wissenserweiterung – detaillierte Erläuterung
  • ES6 Neue Features 2: Detaillierte Erläuterung von Iterator (Durchlauf) und For-of-Schleife
  • Beispiel einer ES6-Verzeichnisdurchquerungsfunktion
  • Analyse der Iterator- und for..of..-Traversal-Nutzung in ES6
  • Detaillierte Erklärung des regulären Ausdrucks RegExp, einer neuen Funktion von ES9
  • Grundlegendes zu JavaScript-Modifikatoren in ES7
  • Detaillierte Erklärung zur Verwendung von Async/await in ES7
  • Detaillierte Erläuterung der Verwendung von Await in ES7 zur Reduzierung der Callback-Verschachtelung

<<:  MySQL max_allowed_packet-Einstellung

>>:  So gehen Sie mit verstümmelten Zeichen in der MySQL-Datenbank um

Artikel empfehlen

So konfigurieren Sie WordPress mit Nginx

Zuvor hatte ich WordPress selbst erstellt, aber d...

Beispiel für die Verwendung von Dockerfile zum Erstellen eines Nginx-Images

Einführung in Dockerfile Docker kann automatisch ...

Ein kurzes Verständnis der Unterschiede zwischen MySQL InnoDB und MyISAM

Vorwort MySQL unterstützt viele Arten von Tabelle...

ThingJS-Partikeleffekte, um Regen- und Schneeeffekte mit einem Klick zu erzielen

Inhaltsverzeichnis 1. Partikeleffekte 2. Laden Si...

Detaillierte Schritte zum Konfigurieren virtueller Hosts in nginx

Virtuelle Hosts verwenden spezielle Software- und...

Einigen Eigenschaften in CSS geht ein "*" oder "_" voraus.

Einigen Eigenschaften in CSS geht ein "*&quo...

So berechnen Sie mit Linux den von zeitgesteuerten Dateien belegten Speicherplatz

Öffnen Sie den Editor für geplante Aufgaben. Cent...

Detaillierte Erklärung zur Verwendung von Eslint in Vue

Inhaltsverzeichnis 1. Beschreibung 2. Laden Sie d...

Detaillierte Erklärung der Angular-Komponentenprojektion

Inhaltsverzeichnis Überblick 1. Einfaches Beispie...