Generatorfunktioner i JavaScript

Generatorfunktioner i JavaScript

I den här artikeln kommer vi att förklara generatorfunktioner i JavaScript.

YouTube Video

Generatorfunktioner i JavaScript

Generatorfunktioner i JavaScript är speciella funktioner som skiljer sig från vanliga funktioner genom att de kan utföra lat exekvering och pausa och återuppta. Genom att förstå generatorfunktioner kan du effektivt hantera asynkrona operationer och sekventiell bearbetning av stora datamängder. Här kommer vi att ge en detaljerad förklaring av hur generatorfunktioner fungerar, hur man använder dem och praktiska användningsfall.

Vad är generatorfunktioner?

En generatorfunktion definieras med function* (en funktionsdefinition med en asterisk) och till skillnad från vanliga funktioner kan den pausa exekveringen mitt i och återuppta den samtidigt som dess tillstånd bibehålls. Generatorfunktioner möjliggör "lat exekvering" och returnerar resultat stegvis, vilket möjliggör effektiv minneshantering och sekventiell bearbetning.

Syntax

1function* generatorFunction() {
2    yield 'First value';
3    yield 'Second value';
4    return 'Done';
5}

På detta sätt kan en generatorfunktion ha flera yield-uttryck och använda yield för att pausa sin exekvering. När en generatorfunktion anropas, exekveras inte funktionens kropp omedelbart, och ett generatorobjekt returneras. Du kan anropa next()-metoden på detta objekt för att återuppta funktionen från den punkt där den pausades.

Grundläggande användning av generatorfunktioner

Nästa steg är att titta på ett grundläggande exempel på hur man använder generatorfunktioner.

 1function* simpleGenerator() {
 2    yield 1;
 3    yield 2;
 4    yield 3;
 5}
 6
 7const gen = simpleGenerator();
 8
 9console.log(gen.next()); // { value: 1, done: false }
10console.log(gen.next()); // { value: 2, done: false }
11console.log(gen.next()); // { value: 3, done: false }
12console.log(gen.next()); // { value: undefined, done: true }

En viktig punkt att notera här är att generatorn returnerar värden varje gång med yield, och så länge done-egenskapen är false innebär det att det finns fler värden att hämta. Det sista anropet till next() returnerar done: true, vilket indikerar att generatorn är färdig.

Nyckelordet yield och värden för paus

yield är ett nyckelord som anger en pauspunkt inom en generatorfunktion. Värdet till höger om yield returneras när next() anropas. Dessutom möjliggör yield tvåvägskommunikation. Med andra ord, när ett värde skickas som ett argument till next()-metoden, skickas det värdet till generatorfunktionen.

 1function* generatorWithYield() {
 2    const value1 = yield 'First yield';
 3    console.log('Received value:', value1);
 4    const value2 = yield 'Second yield';
 5    console.log('Received value:', value2);
 6}
 7
 8const gen = generatorWithYield();
 9
10console.log(gen.next());        // { value: 'First yield', done: false }
11console.log(gen.next('Apple')); // Received value: Apple
12                                // { value: 'Second yield', done: false }
13console.log(gen.next('Banana'));// Received value: Banana
14                                // { value: undefined, done: true }

I det här exemplet skickar anropet next('Apple') värdet 'Apple' till generatorfunktionen, där det används i funktionen.

Hantera generatorns tillstånd

Generatorer kan bibehålla sitt exekveringstillstånd, vilket möjliggör en koncis representation av långa loopar eller sekventiell bearbetning. Följande exempel visar en generator som producerar siffror på obestämd tid.

 1function* infiniteGenerator() {
 2    let i = 0;
 3    while (true) {
 4        yield i++;
 5        if (i > 10) {
 6            break;
 7        }
 8    }
 9}
10
11const gen = infiniteGenerator();
12
13console.log(gen.next().value); // 0
14console.log(gen.next().value); // 1
15console.log(gen.next().value); // 2
16// Continues...

Den här generatorn producerar siffror kontinuerligt med hjälp av en while(true)-slinga, vilket gör att du kan hämta värden vid behov. Detta möjliggör effektiv bearbetning av stora datamängder.

Användningsområden för generatorfunktioner

Generatorfunktioner är lämpliga för att köra flera processer sekventiellt. Till exempel är de användbara för att bearbeta API-förfrågningar sekventiellt eller för att dela upp och bearbeta stora filer.

1function* apiRequestGenerator() {
2    yield fetch('https://codesparklab.com/json/example1.json');
3    yield fetch('https://codesparklab.com/json/example2.json');
4    yield fetch('https://codesparklab.com/json/example3.json');
5}

Generatorer, som kan användas för asynkron bearbetning, är därmed mycket fördelaktiga för effektiv sekventiell datahantering.

Asynkrona generatorer

Asynkrona generatorer, som introducerades i ES2018, låter dig returnera asynkrona värden sekventiellt genom att kombinera async och yield. Detta gör det möjligt att skriva asynkron bearbetning kortfattat i kombination med await.

Syntax

 1async function* asyncGenerator() {
 2    yield await Promise.resolve(1);
 3    yield await Promise.resolve(2);
 4    yield await Promise.resolve(3);
 5}
 6
 7const gen = asyncGenerator();
 8
 9(async () => {
10    for await (const value of gen) {
11        console.log(value); // 1, 2, 3
12    }
13})();

Asynkrona generatorer kan hämta värden sekventiellt med hjälp av en for await...of-slinga. Detta mönster är särskilt användbart vid hantering av asynkrona datastreamar.

Praktiskt exempel: Förenkla asynkron bearbetning med generatorer

Generatorfunktioner används också för att förenkla flödet av asynkron bearbetning. Till exempel kan du kombinera yield och Promise, som visas nedan, för att skriva asynkrona operationer så att de verkar synkrona.

 1function* asyncFlow() {
 2    const data1 = yield fetch('https://codesparklab.com/json/example1.json');
 3    console.log(data1);
 4    const data2 = yield fetch('https://codesparklab.com/json/example2.json');
 5    console.log(data2);
 6}
 7
 8const gen = asyncFlow();
 9
10function handleAsync(generator) {
11    const next = (promise) => {
12        promise.then((result) => {
13        const { value, done } = generator.next(result);
14        if (!done) {
15            next(value);
16        }
17        });
18    };
19
20    next(generator.next().value);
21}
22
23handleAsync(gen);

Denna kod gör API-förfrågningar sekventiellt med hjälp av en generator och bearbetar resultaten.

Sammanfattning

Generatorfunktioner är en av JavaScripts kraftfulla funktioner, med förmåga att pausa och återuppta körningen av en funktion. Detta möjliggör sekventiell bearbetning, asynkron bearbetning och effektiv hantering av stora datamängder. Att förstå generatorer är ett viktigt steg mot att bemästra avancerade tekniker i JavaScript.

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