Generatorfunktioner i TypeScript

Generatorfunktioner i TypeScript

Den här artikeln förklarar generatorfunktioner i TypeScript.

Du kan lära dig allt från grunderna i hur man använder generatorfunktioner till avancerade exempel kombinerade med asynkron bearbetning, tillsammans med kodexempel.

YouTube Video

Generatorfunktioner

Generatorfunktioner i TypeScript erbjuder liknande funktionalitet som JavaScripts generatorfunktioner. Generatorfunktioner definieras med function* (en funktionsdeklaration med en asterisk) och är speciella funktioner som kan pausa och återuppta exekvering till skillnad från vanliga funktioner.

När en generatorfunktion anropas returneras en iterator som genererar värden ett i taget via denna iterator, och du kan pausa exekveringen med nyckelordet yield eller skicka värden utifrån.

Grundläggande syntax för generatorfunktioner

 1function* myGenerator(): Generator<number, void, unknown> {
 2    yield 1;
 3    yield 2;
 4    yield 3;
 5}
 6
 7const gen = myGenerator();
 8
 9console.log(gen.next().value); // 1
10console.log(gen.next().value); // 2
11console.log(gen.next().value); // 3
12console.log(gen.next().done);  // true (Iteration finished)
  • Definiera en generatorfunktion med function* myGenerator().
  • Nyckelordet yield pausar funktionens exekvering samtidigt som det returnerar ett värde.
  • Varje gång metoden next() anropas återupptas exekveringen av generatorfunktionen och fortsätter till nästa yield.

next() returnerar ett objekt som innehåller nästa värde och en done-egenskap. När done är true indikerar det att alla värden har genererats och att generatorns process är slutförd.

Användningsområden för generatorfunktioner

Att använda generatorfunktioner möjliggör en enkel representation av sekventiell bearbetning. I följande exempel skapar vi en generatorfunktion som genererar en sekvens av nummer.

 1function* sequenceGenerator(start: number = 0, step: number = 1) {
 2    let current = start;
 3    while (true) {
 4        yield current;
 5        current += step;
 6    }
 7}
 8
 9const seq = sequenceGenerator(1, 2);
10
11console.log(seq.next().value); // 1
12console.log(seq.next().value); // 3
13console.log(seq.next().value); // 5
  • I detta exempel genererar sequenceGenerator en obestämt ökande sekvens av nummer. Använd yield för att returnera värden vid varje steg och generera nästa värde vid efterföljande anrop.

Skicka värden till next

Metoden next() kan ta emot ett värde som kan skickas in i generatorfunktionen.

 1function* adder() {
 2    const num1 = yield;
 3    const num2 = yield;
 4    yield num1 + num2;
 5}
 6
 7const addGen = adder();
 8addGen.next();          // Initialization
 9addGen.next(5);         // Set 5 to num1
10const result = addGen.next(10).value; // Set 10 to num2 and get result
11console.log(result);    // 15
  • I detta exempel skickar next(5) och next(10) sina respektive värden till generatorfunktionen, och yield num1 + num2 returnerar deras summa.

return och throw

  • return(value) kan avsluta generatorn och returnera det angivna värdet.
  • throw(error) kan kasta ett undantag i generatorn, som används för att hantera undantag inom generatorn.
 1function* testGenerator() {
 2    try {
 3        yield 1;
 4        yield 2;
 5    } catch (e) {
 6        console.error("Error caught:", e);
 7    }
 8}
 9
10const gen = testGenerator();
11console.log(gen.next().value); // 1
12gen.throw(new Error("An error occurred!")); // Error caught: An error occurred!
  • I detta exempel används throw-metoden för att generera ett fel i generatorn, och detta fel fångas inom generatorn.

Typdefinition i TypeScript

Typdefinitionen för en generatorfunktion kan anges i följande format.

1// Generator<YieldType, ReturnType, NextType>
2function* myGenerator(): Generator<number, void, unknown> {
3    yield 1;
4    yield 2;
5    yield 3;
6}
  • Du anger typer i formen Generator<YieldType, ReturnType, NextType>.
    • YieldType är typen av värdet som returneras av yield.
    • ReturnType är typen av värdet som returneras av return.
    • NextType är typen av värdet som skickas till next().

I följande exempel anges specifika typer för att använda generatorn säkert med typer.

 1function* numberGenerator(): Generator<number, void, number> {
 2    const num1 = yield 1;
 3    const num2 = yield num1 + 2;
 4    yield num2 + 3;
 5}
 6
 7const gen = numberGenerator();
 8
 9console.log(gen.next().value);   // 1
10console.log(gen.next(10).value); // 12 (10 + 2)
11console.log(gen.next(20).value); // 23 (20 + 3)

Generatorer och Asynkron Bearbetning

Generatorer kan också användas för asynkron bearbetning. Du kan till exempel använda yield för att vänta på resultat från asynkrona operationer medan du fortsätter med sekventiell bearbetning. Men i TypeScript eller JavaScript används async/await oftare.

1function* asyncTask() {
2    const result1 = yield fetch("https://codesparklab.com/json/example1.json");
3    console.log(result1);
4
5    const result2 = yield fetch("https://codesparklab.com/json/example2.json");
6    console.log(result2);
7}

Även om du kan bearbeta asynkrona operationer sekventiellt med generatorer används de inte ofta för asynkron bearbetning eftersom Promises och async/await är mer praktiska.

Sammanfattning

  • Generatorfunktioner är speciella funktioner definierade med function* som kan returnera värden med yield medan funktionen pausar körningen.
  • Använd next() för att återuppta generatorn och ta emot värden. Dessutom kan du skicka värden till generatorn med hjälp av next(value).
  • Du kan använda return() och throw() för att avsluta generatorfunktioner eller hantera fel.
  • När du använder generatorer i TypeScript kan du använda typdefinitioner för att skriva typesäker kod.

Generatorer är kraftfulla verktyg som låter dig flexibelt styra iteration.

Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.

YouTube Video